<?php

// +----------------------------------------------------------------------
// | 合同服务层
// +----------------------------------------------------------------------
// | 主要服务于合同
// +----------------------------------------------------------------------
// | 错误编码头 239xxx
// +----------------------------------------------------------------------
namespace common\service;

use common\exception\LogicException;
use common\model\ContractModel;
use common\model\ContractTemplateModel;
use common\model\EntityModel;
use common\model\OrderModel;
use common\model\OrderTaskFileListModel;
use common\model\OrderTaskListModel;
use common\model\OrderTaskUpstreamVersionModel;
use common\model\ProjectMemberModel;
use common\model\ProjectModel;
use common\model\ReviewRequestModel;
use common\model\ReviewRequestNodeModel;
use common\model\SettlementModel;
use common\model\StatusModel;
use common\model\StepCategoryModel;
use common\model\TaskModel;
use common\model\TaskRelationModel;
use common\model\UserModel;
use common\model\VersionModel;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;
use think\Hook;
use think\module\Module;
use Throwable;
use Webman\Stomp\Client;

class OrderService
{
    /**    @var OrderModel */
    private $orderModel;

    /** @var OrderTaskListModel */
    private $orderTaskListModel;
    private $orderTaskFileListModel;

    // 单例工具
    use SingletonTrait;

    public function __construct()
    {
        $this->orderModel = model(OrderModel::class);
        $this->orderTaskListModel = model(OrderTaskListModel::class);
        $this->orderTaskFileListModel = model(OrderTaskFileListModel::class);
    }


    /**
     * 提交订单
     * @param $data
     * @return array
     * @throws Throwable
     */
    public function create($data)
    {
        /**
         * 分配任务给外部供应商
         *
         * 工序分类任务标记为已经生成过订单
         *
         * 生成订单
         *
         * 提交审核
         *
         */
        $taskModel = model(TaskModel::class);
        $orderModel = model(OrderModel::class);
        $orderTaskListModel = model(OrderTaskListModel::class);

        $stepCategoryModel = model(StepCategoryModel::class);
        $stepCategoryIds = array_column($data, 'step_category_id');
        $stepCategoryDataAssoc = $stepCategoryModel->where(['id' => ['IN', implode(',', $stepCategoryIds)]])->select();
        $stepCategoryDataAssoc = array_column($stepCategoryDataAssoc, "name", 'id');
        $res = [];
        $orderModule = Module::$moduleDictData['module_index_by_code']['order'];
        $reviewRequestService = ReviewRequestService::getInstance();
        $orderDataList = [];
        $tenantGroupOrder = [];
        $taskModel->startTrans();
        try {
            foreach ($data as $order) {
                $tmpRes = [];
                $order["type"] = $order["type"] ?? "outside";
                $assignStatus = TaskModel::ASSIGN_STATUS_WAIT_CONFIRM;
                //集团订单需要存入集团id
                if ($order["type"] == "tenant_group") {
                    if (!isset($order["tenant_group_id"])) {
                        throw new LogicException("tenant_group_id not exist", ErrorCode::DATA_INVALID);
                    }

                    if (!isset($order["party_b_resp_producer_id"])) {
                        throw new LogicException("party_b_resp_producer_id not exist", ErrorCode::DATA_INVALID);
                    }

                    $assignStatus = TaskModel::ASSIGN_STATUS_EXECUTOR;
                }

                $orderNumber = date("YmdH") . random_int(11111, 99999);
                $tasks = $order['task_list'];
                if (empty($tasks)) {
                    // 任务列表为空 直接跳过
                    continue;
                }
                // 查询出一条任务 用来填充订单的信息
                $taskIdData = array_column($tasks, 'task_id');

                //供应商在本系统中的用户
                $order['number'] = $orderNumber;
                $order['name'] = $stepCategoryDataAssoc[$order['step_category_id']] . date("YmdHi");
                $order['from_tenant_id'] = auto_fill_tenant_id();
                $order['to_tenant_id'] = $order['tenant_id'];


                // 不允许自己给自己创建订单
                if ($order['to_tenant_id'] == $order['from_tenant_id']) {
                    throw new LogicException('data invalid', ErrorCode::DATA_INVALID);
                }

                $order['start_time'] = date("Y-m-d H:i:s", min(array_column($tasks, 'start_time')));
                $order['end_time'] = date("Y-m-d H:i:s", max(array_column($tasks, 'end_time')));

                // 订单甲方制片负责人
                $order['party_a_resp_producer_id'] = $order['reviewer_user_id'];

                // 任务数
                if (!empty($order['task_list'])) {
                    $order['task_num'] = count($order['task_list']);
                }

                // 添加订单
                unset($order['task_list']);

                $tmpRes['order'] = $orderInsert = $orderModel->addItem($order);
                if (!$orderInsert) {
                    throw_strack_exception($orderModel->getError(), $orderModel->getErrorCode());
                }

                // 允许重复分配

                // 标记任务为待接受,
                //集团化的需要变以及受
                $taskIds = implode(',', $taskIdData);

                $taskModel->execute("UPDATE task SET assign_status ='{$assignStatus}' WHERE id IN ({$taskIds})");


                $tasks = array_map(function ($item) use ($orderInsert) {
                    $item['order_id'] = $orderInsert['id'];
                    unset($item['start_time'], $item['end_time']);
                    return $item;
                }, $tasks);

                $tmpRes['order']['task_list'] = $tasks;
                // 添加订单任务清单
                $orderTaskListModel->addAll($tasks);

                //集团化直接触发 乙方生成任务 ,不进行订单审核
                if ($order["type"] == "tenant_group") {
//                    $this->setTenantGroupStepTaskExecutor($orderInsert);
                    $tenantGroupOrder[] = $orderInsert;
                } else {
                    // 添加订单审批申请
                    // 订单审核 只审核一个节点 又前端提交审核人和角色code
                    $reviewData = [
                        'reviewers' => [
                            [
                                'role_code' => $order['reviewer_role_code'],
                                'user_id' => $order['reviewer_user_id'],
                                'skip' => $order['reviewer_user_id'] == request()->getUserId(),
                            ]
                        ],
                        'data' => [
                            'review_workflow_id' => 0,
                            'name' => "订单{$order['name']}-{$order['number']}",
                            'param' => $order,
                            'link_id' => $orderInsert['id'],
                            'module_id' => $orderModule['id']
                        ]
                    ];
                    $orderDataList[] = [
                        'review_data' => $reviewData,
                        'order' => $tmpRes['order'],
                    ];
                    $reviewRequestService->create($reviewData);
                }
                $res[] = $tmpRes;
            }
            $taskModel->commit();
        } catch (Throwable $e) {
            $taskModel->rollback();
            throw  $e;
        }
        //队列在事务之后执行
        foreach ($tenantGroupOrder as $index => $tenantGroupOrderItem) {
            Client::send("set_tenant_group_step_task_executor",
                build_queue_data_with_xu(['order_id' => $tenantGroupOrderItem['id'],]), $index + 2);
        }

        //通知订单审核人
        try {
            $hookData = [
                'type' => 'create_order',
                'data' => [
                    'order_data_list' => $orderDataList,
                ]
            ];
            Hook::listen('order_create_after', $hookData);
            // 已迁移
//            $this->notifyOrderReviewPeople($orderDataList);
        } catch (Throwable $e) {
            trace(format_exception_info($e), 'ERR');
        }
        return $res;
    }

    /**
     * 查询订单列表
     * @param $param
     * @param $tenantId
     * @return array
     * @throws \Exception
     */
    public function getOrderList($param, $tenantId)
    {

//        $commonService = new CommonService("order");
//        $data = $commonService->select($param, 'order');

        $filter = $param['filter'] ?? [];
        $order = $param['order'] ?? "`order`.id DESC";
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $data['total'] = 0;
        $data['rows'] = [];

        $orderTotal = model(OrderModel::class)->query('select count(*) as count from ' . model(OrderModel::class)
                ->join("order_task_list on order_task_list.order_id = `order`.id", "LEFT")
                ->join("entity on entity.id = order_task_list.entity_id", "LEFT")
                ->join("review_request on review_request.link_id = order.id and review_request.module_id = " . module_by_code('order')['id'], "LEFT")
                ->join("review_request_node on review_request.id = review_request_node.review_request_id", "LEFT")
                ->where($filter)
                ->field('`order`.id')
                ->group('order.id')
                ->buildSql() . ' as orderSubQuery');
        $data['total'] = $orderTotal[0]['count'];

        $orderList = model(OrderModel::class)
            ->join("order_task_list on order_task_list.order_id = `order`.id", "LEFT")
            ->join("entity on entity.id = order_task_list.entity_id", "LEFT")
            ->join("review_request on review_request.link_id = order.id and review_request.module_id = " . module_by_code('order')['id'], "LEFT")
            ->join("review_request_node on review_request.id = review_request_node.review_request_id", "LEFT")
            ->field("`order`.id")
            ->where($filter)
            ->page($page[0], $page[1])
            ->group('order.id')
            ->order($order)
            ->select();
        if (empty($orderList)) {
            return $data;
        }
        $orderIds = array_column($orderList, 'id');

        $data['rows'] = model(OrderModel::class)
            ->where(['order.id' => ['IN', $orderIds]])
            ->order($order)
            ->select();
        $orderIds = array_column($data['rows'], 'id');

        // 任务信息
        $orderTaskData = model(OrderTaskListModel::class)
            ->where([
                'order_id' => ['in', $orderIds],
                'status' => 'default',
            ])
            ->group('order_id')
            ->field('order_id, count(distinct id) as task_num')
            ->select();
        $orderTaskData = array_column($orderTaskData, 'task_num', 'order_id');

        // 合同信息
        $contractData = ContractService::getInstance()->getOrderContractList($orderIds, $tenantId);
        $contractData = array_column($contractData, null, 'order_id');

        // 项目信息
        $projectIds = array_column($data['rows'], 'project_id', 'project_id');
        $projectData = model(ProjectModel::class)->field("id,name,type")->where(['id' => ['IN', implode(',', $projectIds)]])->select();
        $projectData = array_column($projectData, null, 'id');

        // 集查询
        $taskList = model(OrderTaskListModel::class)->where(['order_id' => ['IN', implode(',', $orderIds)]])->select();
        $entityIds = array_column($taskList, 'entity_id', 'entity_id');
        $entityData = model(EntityModel::class)->where(['id' => ['IN', implode(',', $entityIds)]])->field('id,code,initial_episode_code')->select();
        $entityData = array_column($entityData, 'initial_episode_code', 'id');
        $orderEpisodeMap = [];
        foreach ($taskList as $task) {
            if (!empty($entityData[$task['entity_id']])) {
                $orderEpisodeMap[$task['order_id']][$entityData[$task['entity_id']]] = $entityData[$task['entity_id']];
            }
        }


        // 审批信息查询
        $orderModule = Module::$moduleDictData['module_index_by_code']['order'];
        $reviewRequestModel = model(ReviewRequestModel::class);
        $reviewRequestData = $reviewRequestModel->join('review_request_node ON review_request.id = review_request_node.review_request_id', 'LEFT')
            ->field("review_request.link_id as order_id,review_request_node.id")
            ->where([
                'review_request.link_id' => ['IN', implode(',', $orderIds)],
                'review_request.module_id' => $orderModule['id'],
//                'review_request_node.plan_reviewer' => request()->getUserId(),
                'review_request_node.is_reviewed' => "no",
            ])
            ->select();
        $reviewRequestData = array_column($reviewRequestData, null, 'order_id');

        // 创建者查询
        $createdByIds = array_column($data['rows'], 'created_by', 'created_by');
        $personInChargeIds = array_column($data['rows'], 'party_a_person_in_charge', 'party_a_person_in_charge');
        $partyARespProducerIds = array_column($data['rows'], 'party_a_resp_producer_id', 'party_a_resp_producer_id');
        $partyBRespProducerIds = array_column($data['rows'], 'party_b_resp_producer_id', 'party_b_resp_producer_id');
        $createdByIds = array_unique(array_merge($createdByIds, $personInChargeIds, $partyARespProducerIds, $partyBRespProducerIds));
        $userData = model(UserModel::class)->field("json,uuid", true)->where(['id' => ['IN', implode(',', $createdByIds)]])->select();
        $userData = array_column($userData, null, 'id');

        //租户信息查询
        $tenantIdData = array_column($data['rows'], 'from_tenant_id', 'from_tenant_id');
        $tenantIdData = array_merge($tenantIdData, array_column($data['rows'], 'to_tenant_id', 'to_tenant_id'));
        $tenantData = teamones_request('teamones-im', 'tenant_authentication/select', ['param' => [
            'filter' => [
                "tenant_id" => [
                    "-in", implode(',', $tenantIdData)
                ]
            ],
            "fields" => "tenant_id as id,company_name,person_in_charge,person_in_charge_phone,person_in_charge_email"
        ]])['data'];
        $tenantData = array_column($tenantData['rows'], null, 'id');

        //结算信息
        $settlements = model(SettlementModel::class)->where(['is_reviewed' => "yes", 'order_id' => ['IN', implode(',', $orderIds)]])->select();
        $settlementsMap = array_column($settlements, null, 'order_id');

        $orderTaskWaitReview = [];
        if (!empty($param['type']) && $param['type'] == 1) {
            // 乙方查询
            // 订单审核管理待处理
            $orderTaskWaitReview = model(OrderTaskListModel::class)
                ->where(['order_id' => ['IN', $orderIds], 'deal_status' => ['IN', 'to_submit,pending']])
                ->group('order_id')
                ->field('order_id')
                ->select();
            $orderTaskWaitReview = array_column($orderTaskWaitReview, 'order_id', 'order_id');

            // 乙方上传查询
            $orderUploadList = model(OrderTaskFileListModel::class)->alias('otfl')
                ->join('order_task_upstream_version otuv on otuv.task_id = otfl.task_id and otuv.to_tenant_id = otfl.to_tenant_id and otuv.from_tenant_id = otfl.from_tenant_id', 'LEFT')
                ->where(['otfl.order_id' => ['IN', $orderIds], 'otfl.from_tenant_id' => $tenantId])
                ->field('otfl.order_id,max(otuv.version_id) version_id')
                ->group('otfl.order_id,otfl.task_id')
                ->select();
            $versionIdList = array_filter(array_column($orderUploadList, 'version_id'), function ($item) {
                return !empty($item);
            });
            $versionList = [];
            if (!empty($versionIdList)) {
                $versionList = model(VersionModel::class)->where(['id' => ['IN', $versionIdList], 'is_publish' => 'yes'])->field('id,is_uploaded')->select();
                $versionList = array_column($versionList, 'is_uploaded', 'id');
            }
            $needUploadedOrderIdList = [];
            foreach ($orderUploadList as $item) {
                if ($item['version_id'] > 0 && isset($versionList[$item['version_id']]) && $versionList[$item['version_id']] === 'no') {
                    $needUploadedOrderIdList[] = $item['order_id'];
                }
            }
            // 乙方下载查询
            $orderUploadList = model(OrderTaskFileListModel::class)
                ->alias('otfl')
                ->join('order_task_upstream_version otuv on otuv.task_id = otfl.task_id and otuv.to_tenant_id = otfl.to_tenant_id and otuv.from_tenant_id = otfl.from_tenant_id', 'LEFT')
                ->join('version v on otuv.version_id = v.id')
                ->where(['otfl.order_id' => ['IN', $orderIds], 'otfl.to_tenant_id' => $tenantId, 'v.is_uploaded' => 'yes'])
                ->field('otfl.order_id,max(otuv.version_id) version_id')
                ->group('otfl.order_id,otfl.task_id')
                ->select();
            $versionIdList = array_filter(array_column($orderUploadList, 'version_id'), function ($item) {
                return !empty($item);
            });
            $versionList = [];
            if (!empty($versionIdList)) {
                $versionList = model(OrderTaskUpstreamVersionModel::class)
                    ->alias('otuv')
                    ->join('version v on v.id = otuv.version_id')
                    ->where(['otuv.to_tenant_id' => $tenantId, 'otuv.version_id' => ['IN', $versionIdList], 'v.is_uploaded' => 'yes'])
                    ->field('otuv.version_id,otuv.is_download')
                    ->select();
                $versionList = array_column($versionList, 'is_download', 'version_id');
            }

            $needDownloadOrderIdList = [];
            foreach ($orderUploadList as $item) {
                if ($item['version_id'] > 0 && isset($versionList[$item['version_id']]) && $versionList[$item['version_id']] === 'no') {
                    $needDownloadOrderIdList[] = $item['order_id'];
                }
            }

        } else {
            // 甲方查询

            // 甲方上传查询
            $orderUploadVersionList = model(OrderTaskFileListModel::class)->alias('otfl')
                ->join('order_task_upstream_version otuv on otuv.task_id = otfl.task_id and otuv.to_tenant_id = otfl.to_tenant_id and otuv.from_tenant_id = otfl.from_tenant_id', 'LEFT')
                ->where(['otfl.order_id' => ['IN', $orderIds], 'otfl.from_tenant_id' => $tenantId])
                ->field('otfl.order_id,otfl.task_id,max(otuv.version_id) as version_id')
                ->group('otfl.order_id,otfl.task_id')
                ->select();
            $versionIdList = array_filter(array_column($orderUploadVersionList, 'version_id'), function ($item) {
                return !empty($item);
            });
            $versionList = [];
            if (!empty($versionIdList)) {
                $versionList = model(VersionModel::class)->where(['id' => ['IN', $versionIdList], 'is_publish' => 'yes'])->field('id,is_uploaded')->select();
                $versionList = array_column($versionList, 'is_uploaded', 'id');
            }
            $needUploadedOrderIdList = [];
            foreach ($orderUploadVersionList as $item) {
                if ($item['version_id'] > 0 && isset($versionList[$item['version_id']]) && $versionList[$item['version_id']] === 'no') {
                    $needUploadedOrderIdList[] = $item['order_id'];
                }
            }

            // 甲方下载查询
            $orderDownloadList = model(OrderTaskFileListModel::class)->alias('otfl')
                ->join('order_task_upstream_version otuv on otuv.task_id = otfl.task_id and otuv.to_tenant_id = otfl.to_tenant_id and otuv.from_tenant_id = otfl.from_tenant_id', 'LEFT')
                ->join('version v on v.id = otuv.version_id')
                ->where(['otfl.order_id' => ['IN', $orderIds], 'otfl.to_tenant_id' => $tenantId, 'v.is_uploaded' => 'yes'])
                ->field('otfl.order_id,max(otuv.version_id) version_id')
                ->group('otfl.order_id,otfl.task_id')
                ->select();
            $versionIdList = array_filter(array_column($orderDownloadList, 'version_id'), function ($item) {
                return !empty($item);
            });
            $versionList = [];
            if (!empty($versionIdList)) {
                $versionList = model(OrderTaskUpstreamVersionModel::class)
                    ->alias('otuv')
                    ->join('version v on v.id = otuv.version_id')
                    ->where(['otuv.version_id' => ['IN', $versionIdList], 'otuv.to_tenant_id' => $tenantId, 'v.is_uploaded' => 'yes'])
                    ->field('otuv.version_id,otuv.is_download')
                    ->select();
                $versionList = array_column($versionList, 'is_download', 'version_id');
            }

            $needDownloadOrderIdList = [];
            foreach ($orderDownloadList as $item) {
                if ($item['version_id'] > 0 && isset($versionList[$item['version_id']]) && $versionList[$item['version_id']] === 'no') {
                    $needDownloadOrderIdList[] = $item['order_id'];
                }
            }
        }

        // 查询环节
        $stepCategoryIds = array_column($data['rows'], 'step_category_id');
        $stepCategoryData = model(StepCategoryModel::class)->where(['id' => ['IN', $stepCategoryIds]])->select();
        $stepCategoryMap = array_column($stepCategoryData, null, 'id');


        $data['rows'] = array_map(function ($item) use (&$tenantData, &$userData, &$reviewRequestData, &$contractData, &$settlementsMap, &$orderTaskData, &$orderTaskWaitReview, $needUploadedOrderIdList, $needDownloadOrderIdList, &$projectData, $orderEpisodeMap, $stepCategoryMap) {
            $item['task_num'] = $orderTaskData[$item['id']] ?? 0;
            $item['from_tenant'] = $tenantData[$item['from_tenant_id']] ?? null;
            $item['to_tenant'] = $tenantData[$item['to_tenant_id']] ?? null;
            $item['creator'] = $userData[$item['created_by']] ?? null;
            $item['party_a_person_in_charge'] = $userData[$item['party_a_person_in_charge']] ?? null;
            $item['party_a_resp_producer'] = $userData[$item['party_a_resp_producer_id']] ?? null;
            $item['party_b_resp_producer'] = $userData[$item['party_b_resp_producer_id']] ?? null;
            $item['review_request_node'] = $reviewRequestData[$item['id']] ?? null;
            $item['contract'] = $contractData[$item['id']] ?? null;
            $item['settlement'] = $settlementsMap[$item['id']] ?? null;
            $item['review_manage_notify'] = isset($orderTaskWaitReview[$item['id']]);
            $item['upload_notify'] = in_array($item['id'], $needUploadedOrderIdList);
            $item['download_notify'] = in_array($item['id'], $needDownloadOrderIdList);
            $item['project'] = $projectData[$item['project_id']] ?? '';
            $item['episode_list'] = [];
            $item['step_category_info'] = $stepCategoryMap[$item['step_category_id']] ?? null;
            if (!empty($orderEpisodeMap[$item['id']])) {
                $item['episode_list'] = array_keys($orderEpisodeMap[$item['id']]);
            }
//                $item['end_time'] = get_format_date($item['end_time'], 1);
//                $item['created'] = get_format_date($item['created'], 1);
//                $item['updated'] = get_format_date($item['updated'], 1);
            return $item;
        }, $data['rows']);
        return $data;

    }

    /**
     * 查询订单详情
     * @param $param
     * @param $tenantId
     * @return mixed
     * @throws Exception
     */
    public function getOrderDetail($param, $tenantId)
    {
        $commonService = CommonService::instance("order");
        $order = $commonService->find($param, 'order');
        if (empty($order)) {
            return null;
        }

        $statusList = model(StatusModel::class)->select();
        $statusMap = array_column($statusList, null, 'id');

        $taskModel = model(TaskModel::class);
        // 分类信息
        $order['step_category'] = model(StepCategoryModel::class)->where(['id' => $order['step_category_id']])->find();
        $order['task_list'] = model(OrderTaskListModel::class)
            ->join('task on task.id = order_task_list.task_id')
            ->where(['order_id' => $order['id'], 'status' => OrderTaskListModel::STATUS_DEFAULT])
            ->field('order_task_list.*')
            ->select();
        // 任务
        $taskIdData = array_column($order['task_list'], 'task_id', 'task_id');
        $task = $taskModel->where(['id' => ['IN', implode(',', $taskIdData)]])->field('id,name,code,man_hour,entity_id,entity_module_id,plan_start_time,plan_end_time,plan_duration,executor,executor_tenant_id,assign_status,assignee_producer,json')->select();
        $task = array_column($task, null, 'id');

        // 任务实际工时计算
        $taskService = TaskService::getInstance();
        $taskActualManHour = $taskService->getTaskListActualManHour(['filter' => ['id' => ['IN', implode(',', $taskIdData)]]]);
        if (!is_array($taskActualManHour)) {
            $taskActualManHour = [];
        }
        $taskActualManHour = array_column($taskActualManHour, null, 'task_id');
        $task = array_map(function ($item) use ($taskActualManHour, $statusMap) {
            $taskJson = json_decode($item['json'], true);
            $item['total_manhour_sec'] = $item['in_progress_manhour_sec'] = $item['done_manhour_sec'] = 0;
            $item['is_active'] = false;
            if (isset($taskActualManHour[$item['id']])) {
                $item['total_manhour_sec'] = $taskActualManHour['total'];
                $item['in_progress_manhour_sec'] = $taskActualManHour['in_progress'];
                $item['done_manhour_sec'] = $taskActualManHour['done'];
                $item['is_active'] = $taskActualManHour['is_active'];
            }
            $item['task_status'] = $statusMap[$taskJson['task_status']] ?? null;
            unset($item['json']);
            $item['is_dismantle_task'] = $taskJson['is_dismantle_task'] ?? null;
            $item['dismantle_name'] = $taskJson['dismantle_name'] ?? null;
            return $item;
        }, $task);

        $order['task_list'] = array_map(function ($item) use ($task) {
            $item['task'] = $task[$item['task_id']] ?? null;
            return $item;
        }, $order['task_list']);

        $order['contract'] = ContractService::getInstance()->getOrderContract($order['id'], $tenantId);
        $order['contract'] = !empty($order['contract']) ? $order['contract'] : null;
        if (!empty($order['contract'])) {
            $order['contract'] = CommonService::getFormatAttrData(model(ContractModel::class), $order['contract']);
        }

        // 审批信息查询
        $orderModule = Module::$moduleDictData['module_index_by_code']['order'];
        $reviewRequestModel = model(ReviewRequestModel::class);
        $order['review_request_node'] = $reviewRequestModel->join('review_request_node ON review_request.id = review_request_node.review_request_id', 'LEFT')
            ->field("review_request.link_id as order_id,review_request_node.id")
            ->where([
                'review_request.link_id' => $order['id'],
                'review_request.module_id' => $orderModule['id'],
                'review_request_node.plan_reviewer' => request()->getUserId(),
                'review_request_node.is_reviewed' => "no",
            ])
            ->find();
        $order['review_request_node'] = !empty($order['review_request_node']) ? $order['review_request_node'] : null;

        //租户信息查询
        $tenantIdData = [$order['from_tenant_id'], $order['to_tenant_id']];
        $tenantData = teamones_request('teamones-im', 'tenant_authentication/select', ['param' => [
            'filter' => [
                "tenant_id" => [
                    "-in", implode(',', $tenantIdData)
                ]
            ],
            "fields" => "tenant_id as id,company_name,person_in_charge,person_in_charge_phone,person_in_charge_email,company_web_site,unified_social_credit_code,company_registered_address,bank_of_deposit,bank_account"
        ]])['data'];
        $tenantData = array_column($tenantData['rows'], null, 'id');
        $order['from_tenant'] = $tenantData[$order['from_tenant_id']] ?? null;
        $order['to_tenant'] = $tenantData[$order['to_tenant_id']] ?? null;

        //实体id
        $sequenceIdList = [];
        $sequenceModuleId = Module::$moduleDictData['module_index_by_code']['sequence']['id'];
        $entityIdData = array_column($order['task_list'], 'entity_id', 'entity_id');
        $entityData = model(EntityModel::class)->where(['id' => ['IN', implode(',', $entityIdData)]])->field('id,name,code,initial_episode_code,module_id,entity_id,module_id,entity_module_id,start_time,end_time,json,estimate_hours,cost_hours,plan_start_time,plan_end_time,showings_number')->select();
        $entityData = array_map(function ($item) use (&$sequenceIdList, $sequenceModuleId) {
            $module = Module::$moduleDictData['module_index_by_id'][$item['module_id']];
            if ($item['entity_module_id'] === $sequenceModuleId) {
                $sequenceIdList[$item['entity_id']] = $item['entity_id'];
            }
            CommonService::getFormatAttrData(model(get_module_model_name($module)), $item);
            if (isset($item['json'])) {
                foreach ($item['json'] as $jsonField => $jsonValue) {
                    $field = explode('_', $jsonField);
                    if (count($field) > 1) {
                        $jsonField = str_replace_once(array_shift($field) . '_', '', $jsonField);
                    }
                    $item[$jsonField] = $jsonValue;
                }
                unset($item['json']);
            }
            return $item;
        }, $entityData);
        // 查询序列信息
        $sequenceList = [];

        if (count($sequenceIdList) > 0) {
            $sequenceList = model(EntityModel::class)->where(['id' => ['IN', $sequenceIdList]])->field('id,name,code')->select();
            $sequenceList = array_column($sequenceList, null, 'id');
        }

        $entityData = array_column($entityData, null, 'id');
        $entityFormat = function ($item) use ($entityData, $sequenceList) {
            $item['entity'] = $entityData[$item['entity_id']] ?? null;
            if (!empty($item['entity'])) {
                // 使用实体的Entity module_code来引用实体数据
                $item[Module::$moduleDictData['module_index_by_id'][$item['entity']['module_id']]['code']] = &$item['entity'];
            }
            return $item;
        };
        if (count($sequenceList)) {
            $entityFormatSub = $entityFormat;
            $entityFormat = function ($item) use ($entityFormatSub, &$sequenceList) {
                $item = $entityFormatSub($item);
                $item['sequence'] = [];
                if (!empty($item['entity']['entity_id']) && !empty($sequenceList[$item['entity']['entity_id']])) {
                    $item['sequence'] = $sequenceList[$item['entity']['entity_id']];
                }
                return $item;
            };
        }
        // 格式化实体数据
        $order['task_list'] = array_map($entityFormat, $order['task_list']);
        // 用户信息查询
        $userIdData = [$order['created_by'], $order['party_a_person_in_charge'], $order['party_a_resp_producer_id'], $order['party_b_resp_producer_id']];
        if (!empty($order['contract'])) {
            $userIdData[] = $order['contract']['party_a_signer'];
            $userIdData[] = $order['contract']['party_b_signer'];
        }
        // 任务执行人
        foreach ($task as $taskItem) {
            if (!empty($taskItem['executor'])) {
                $userIdData[] = $taskItem['executor'];
            }
        }
        $userIdData = array_unique($userIdData);

        $userData = model(UserModel::class)->field("json,uuid", true)->where(['id' => ['IN', implode(',', $userIdData)]])->select();
        $userData = array_column($userData, null, 'id');

        $order['task_list'] = array_map(function ($item) use ($userData) {
            if (!empty($item['task'])) {
                $item['task']['executor_info'] = $userData[$item['task']['executor']] ?? null;
            }
            return $item;
        }, $order['task_list']);

        if (!empty($order['contract'])) {
            $order['contract']['party_a_signer'] = $userData[$order['contract']['party_a_signer']] ?? null;
            $order['contract']['party_b_signer'] = $userData[$order['contract']['party_b_signer']] ?? null;
        }
        $order['party_a_resp_producer'] = $userData[$order['party_a_resp_producer_id']] ?? null;
        $order['party_b_resp_producer'] = $userData[$order['party_b_resp_producer_id']] ?? null;
        $order['creator'] = $userData[$order['created_by']] ?? null;
        $order['party_a_person_in_charge'] = $userData[$order['party_a_person_in_charge']] ?? null;
        $order['settlement'] = model(SettlementModel::class)->where(['order_id' => $order['id'], 'is_reviewed' => "yes"])->order("id desc")->find(); // 关联的结算信息 只显示 已审核的

        return $order;
    }

    /**
     * 获得订单审核流配置 id
     * @return integer
     */
    private function getOrderReviewConfig()
    {
        return (int)OptionsService::getInstance()->getOptionsConfigItemData("order_review_config", 'order_created_review');
    }

    /**
     * 更新订单
     * @param array $data
     * @param int $userId
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function update(array $data, int $userId)
    {
        /**
         * 修改订单
         * 1. 检查是否订单的供应商发生变化 如果发生变化 那么任务的分执行人同步发生变化
         * 2. 检查是否任务列表有更新 对比出需要更新的订单任务列表,需要删除的订单任务列表(恢复任务可分配状态),需要新增的订单任务列表
         * 3. 订单修改
         * 4. 订单的上一个未完成审核删除
         * 5. 订单任务列表修改
         * 6. 新增订单审核记录
         */

        $orderModel = model(OrderModel::class);
        $orderTaskListModel = model(OrderTaskListModel::class);
        $res = [];
        $orderModule = Module::$moduleDictData['module_index_by_code']['order'];
        $oldOrder = $orderModel->find($data['id']);
        if (empty($oldOrder)) {
            throw_strack_exception("can`t found order {$data['id']}", ErrorCode::ORDER_NOT_FOUND);
        }
        $reviewRequestActiveFilter = [
            'review_request.link_id' => $data['id'],
            'review_request.module_id' => $orderModule['id'],
            'review_request_node.is_reviewed' => "no",
        ];
        $reviewRequestActive = model(ReviewRequestModel::class)->join('review_request_node ON review_request.id = review_request_node.review_request_id', 'LEFT')->where($reviewRequestActiveFilter)->field("review_request.id")->find();

        $data['party_a_resp_producer_id'] = $data['reviewer_user_id'];
        $needDelete = [];
        $needDeleteTaskItemIdList = [];
        $orderTaskList = [];
        $oldOrderTaskList = model(OrderTaskListModel::class)->where(['order_id' => $data['id']])->select();
        $oldOrderTaskListIdIndexByTaskId = array_column($oldOrderTaskList, 'id', 'task_id');
        $leastTaskIdList = array_column($oldOrderTaskList, 'task_id', 'task_id');
        $isCancelOrder = false;
        // 如果提交了任务列表 检查要更新的数据
        if (array_key_exists('task_list', $data)) {
            $orderTaskList = $data['task_list'];
            $isCancelOrder = empty($orderTaskList);
            unset($data['task_list']);
            $oldOrderTaskIdList = array_column($oldOrderTaskList, 'task_id', 'task_id');
            $currentOrderTaskIdList = array_column($orderTaskList, 'task_id', 'task_id');
            $needUpdate = array_intersect_key($currentOrderTaskIdList, $oldOrderTaskIdList);
            $leastTaskIdList = array_keys($needUpdate);
            $needDelete = array_diff($oldOrderTaskIdList, $currentOrderTaskIdList);
//            $needAdd = array_diff($currentOrderTaskIdList, $oldOrderTaskIdList);
            foreach ($oldOrderTaskList as $oldOrderTaskItem) {
                if (in_array($oldOrderTaskItem['task_id'], $needDelete)) {
                    $needDeleteTaskItemIdList[] = $oldOrderTaskItem['id'];
                }
            }
            $orderTaskList = array_column($orderTaskList, null, 'task_id');
            foreach ($orderTaskList as $taskId => &$orderTaskItem) {
                $orderTaskItem['id'] = $oldOrderTaskListIdIndexByTaskId[$taskId] ?? 0;
            }
            unset($orderTaskItem);
        }
        $reviewWorkflowId = $this->getOrderReviewConfig();
        $reviewRequestService = ReviewRequestService::getInstance();
        $data['status'] = !$isCancelOrder ? "wait_for_party_a_review" : "cancel";
        // 供应商修改检查
        $updateTaskExecutorData = [];
        $supplierChanged = false;
        $toTenantId = $oldOrder['to_tenant_id'];
        if (isset($data['to_tenant_id'])) {
            if ($data['to_tenant_id'] <= 0) {
                throw new LogicException('supplier can`t be null', ErrorCode::SUPPLIER_NOT_EXIST);
            }
            $supplierChanged = $data['to_tenant_id'] != $oldOrder['to_tenant_id'];
            $toTenantId = $data['to_tenant_id'];
        }

        $supplierFindParam = ['param' => ['filter' => [
            'supplier.tenant_id' => $oldOrder['from_tenant_id'],
            'supplier.from_tenant_id' => $toTenantId,
            'supplier.type' => 'outside',
        ]]];
        $supplier = teamones_request('teamones-im', 'supplier/find_supplier', $supplierFindParam)['data'];
        if (empty($supplier)) {
            throw new LogicException("supplier not found", ErrorCode::SUPPLIER_NOT_EXIST);
        }
        // 如果供应商发生了变化 需要重新组装param 和更新任务的分配数据
        if ($supplierChanged) {
            $levelData = $supplier['level_data'] ?? [];
            $levelData = array_column($levelData, null, 'step_category_id');
            $orderJsonFields = json_decode($oldOrder['param'], true);
            $orderJsonFields['company_name'] = $supplier['authentication']['company_name'];
            $orderJsonFields['supplier_id'] = $supplier['id'];
            $orderJsonFields['supplier_level'] = isset($levelData[$oldOrder['step_category_id']]) ? $levelData[$oldOrder['step_category_id']]['level'] : '';
            $data['param'] = $data['param'] ?? [];
            $data['param'] = array_merge($orderJsonFields, $data['param']);
            if (count($leastTaskIdList)) {
                foreach ($leastTaskIdList as $taskId) {
                    $updateTaskExecutorData[] = [
                        'task_id' => $taskId,
                        'supplier_type' => 'outside',
                        'user_id' => $supplier['user_id'],
                        'tenant_id' => $supplier['from_tenant_id'],
                    ];
                }
            }
        }

        unset($data['number']);
        $resetTaskAssignStatus = [
            'executor_tenant_id' => 0,
            'executor' => 0,
            'assignee' => 0,
            'assign_status' => TaskModel::ASSIGN_STATUS_DEFAULT,
            'executor_type' => 'default'
        ];
        $taskAssignService = TaskAssignService::getInstance();
        $orderModel->startTrans();
        try {
            $res['order'] = $updateFlag = $orderModel->modifyItem($data);
            if (!$updateFlag && $orderModel->getErrorCode() != \think\exception\ErrorCode::NO_DATA_HAS_BEEN_CHANGED) {
                throw new LogicException($orderModel->getError(), $orderModel->getErrorCode());
            }
            // 从订单删除任务
            if (count($needDeleteTaskItemIdList)) {
                $this->orderTaskListModel->where(['id' => ['IN', $needDeleteTaskItemIdList]])->delete();
            }
            // 恢复订单任务的可分配状态
            if (count($needDelete)) {
                model(TaskModel::class)->where(['id' => ['IN', $needDelete]])->save($resetTaskAssignStatus);

                // 外包订单重新分配，未分配任务重新释放，更新未处理数据记录
                Client::send('count_pending', build_queue_data_with_xu([
                    'type' => 'assign_task',
                    'mode' => 'add_batch',
                    'data' => $needDelete
                ]));
            }
            // 更新订单任务数据
            foreach ($orderTaskList as $orderTaskItem) {
                if (isset($orderTaskItem['id']) && $orderTaskItem['id'] > 0) {
                    $res['order']['task_list'][] = $flag = $orderTaskListModel->modifyItem($orderTaskItem);
                } else {
                    unset($orderTaskItem['id']);
                    $orderTaskItem['order_id'] = $data['id'];
                    $updateTaskExecutorData[] = [
                        'task_id' => $orderTaskItem['task_id'],
                        'supplier_type' => 'outside',
                        'user_id' => $supplier['user_id'],
                        'tenant_id' => $supplier['from_tenant_id'],
                    ];
                    $res['order']['task_list'][] = $flag = $orderTaskListModel->addItem($orderTaskItem);
                }
                if ($flag === false && $orderTaskListModel->getErrorCode() != \think\exception\ErrorCode::NO_DATA_HAS_BEEN_CHANGED) {
                    throw new LogicException($orderTaskListModel->getError(), $orderTaskListModel->getErrorCode());
                }
            }
            // 修改订单任务的执行人
            if (count($updateTaskExecutorData)) {
                // 重新分配任务
                $taskAssignService->assignTaskToSupplierBatch($updateTaskExecutorData, $userId, $oldOrder['from_tenant_id']);
                // 标记任务为待接受
                $taskIds = implode(',', array_column($updateTaskExecutorData, 'task_id'));
                model(TaskModel::class)->execute("UPDATE task SET assign_status ='wait_confirm' WHERE id IN ({$taskIds})");
            }

            if (!empty($reviewRequestActive)) {
                model(ReviewRequestModel::class)->where(['id' => $reviewRequestActive['id']])->delete();
                model(ReviewRequestNodeModel::class)->where(['review_request_id' => $reviewRequestActive['id']])->delete();
            }
            if (!$isCancelOrder) {
                // 添加订单审批申请
                // 订单审核 只审核一个节点 又前端提交审核人和角色code
                $reviewData = [
                    'reviewers' => [
                        [
                            'role_code' => $data['reviewer_role_code'],
                            'user_id' => $data['reviewer_user_id'],
                            'skip' => $data['reviewer_user_id'] == $userId ? 1 : 0
                        ]
                    ],
                    'data' => [
                        'review_workflow_id' => $reviewWorkflowId,
                        'name' => "订单{$oldOrder['name']}-{$oldOrder['number']}",
                        'param' => $data,
                        'link_id' => $data['id'],
                        'module_id' => $orderModule['id']
                    ]
                ];
                $reviewRequestService->create($reviewData);
            }

            $orderModel->commit();
            return $res;
        } catch (Throwable $e) {
            $orderModel->rollback();
            throw $e;
        }
    }

    /**
     * 乙方确认订单
     * @param $param
     * @param $currentUserId
     * @param $partyBRespProducerId
     * @param $tenantId
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function partyBAcceptOrder($param, $currentUserId, $partyBRespProducerId, $tenantId): array
    {
        $orderId = $param['id'];

        $order = $this->orderModel
            ->where([
                'to_tenant_id' => $tenantId,
                'id' => $orderId,
            ])->find();

        if (empty($order)) {
            throw_strack_exception("can`t found order {$orderId}", ErrorCode::ORDER_NOT_FOUND);
        }
        $order = CommonService::getFormatAttrData($this->orderModel, $order);
        $order['start_time'] = date("Y-m-d H:i:s", $order['start_time']);
        $order['end_time'] = date("Y-m-d H:i:s", $order['end_time']);

        if ($order['status'] != "wait_for_party_b_ensure") {
            throw_strack_exception("order current status can`t do this action", ErrorCode::ORDER_CANNOT_PERFORM_THIS_OPERATION);
        }

        $orderTaskList = $this->orderTaskListModel->where(['order_id' => $orderId])->select();
        $taskIdList = array_column($orderTaskList, 'task_id');
        $res = [];

        $orderStatusCheck = $this->orderModel
            ->lock(true)
            ->find($orderId);
        // 再次判断订单状态是否可操作
        if ($orderStatusCheck['status'] != "wait_for_party_b_ensure") {
            throw_strack_exception("order current status can`t do this action", ErrorCode::ORDER_CANNOT_PERFORM_THIS_OPERATION);
        }
        $this->orderModel->startTrans();
        try {
            //修改订单状态为 待签署
            $order['param']['order_accept_people'] = $currentUserId;
            $res['order'] = $this->orderModel->modifyItem([
                'id' => $orderId,
                'status' => OrderModel::STATUS_PARTYB_ACCEPTED,
                'param' => $order['param'],
                'party_b_resp_producer_id' => $partyBRespProducerId
            ]);
            // 更新任务为已接受状态
            model(TaskModel::class)->where(['id' => ['IN', implode(',', $taskIdList)]])->save(['assign_status' => TaskModel::ASSIGN_STATUS_EXECUTOR]);
            //生成合同
//            $res['contract_info'] = $this->generateOrderContract($order, $tenantId, $currentUserId);
            Client::send("set_tenant_group_step_task_executor", build_queue_data_with_xu(['order_id' => $orderId,]));

            $this->orderModel->commit();
        } catch (Throwable $e) {
            $this->orderModel->rollback();
            throw $e;
        }

        // 建立群聊 async
        try {
            Client::send("create_order_chat", build_queue_data_with_xu(['order_id' => $orderId]));
        } catch (Throwable $e) {
            trace(format_exception_info($e), 'ERR');
        }

        return $res;

    }

    /**
     * 乙方拒绝订单
     * @param $param
     * @param $partyBRespProducerId
     * @param $tenantId
     * @return array|bool
     * @throws Throwable
     */
    private function partyBDenyOrder($param, $partyBRespProducerId, $tenantId)
    {
        $orderId = $param['id'];

        $order = $this->orderModel
            ->where([
                'to_tenant_id' => $tenantId,
                'id' => $orderId,
            ])->find();

        if (empty($order)) {
            throw_strack_exception("can`t found order {$orderId}", ErrorCode::ORDER_NOT_FOUND);
        }
        if ($order['status'] != "wait_for_party_b_ensure") {
            throw_strack_exception("order current status can`t do this action", ErrorCode::ORDER_CANNOT_PERFORM_THIS_OPERATION);
        }
        $this->orderModel->startTrans();
        try {
            // 当前订单lock操作
            $order = $this->orderModel
                ->lock(true)
                ->find($orderId);
            // 再次判断订单状态是否可操作
            if ($order['status'] != "wait_for_party_b_ensure") {
                throw_strack_exception("order current status can`t do this action", ErrorCode::ORDER_CANNOT_PERFORM_THIS_OPERATION);
            }

            //修改订单状态为 乙方拒绝
            $res = $this->orderModel->modifyItem([
                'id' => $orderId,
                'status' => 'party_b_deny',
                'party_b_resp_producer' => $partyBRespProducerId,
            ]);

            // @update 2021年9月3日 拒绝订单不修改任务分配状态 由对方制片编辑订单释放任务
//            model(TaskModel::class)->where(['id' => ['IN', implode(',', $taskIdList)]])->save(['assign_status' => 'rejected']);

            $this->orderModel->commit();

            try {
                // 通知甲方订单接受结果
                $this->notifyPartyASupplierProcessOrderResult($res['id'], false);
            } catch (Throwable $e) {
                trace(format_exception_info($e), 'ERR');
            }

        } catch (Throwable $e) {
            $this->orderModel->rollback();
            throw $e;
        }
        return $res;
    }

    /**
     * 生成订单合同
     * @param $order
     * @param $tenantId
     * @param $signer
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function generateOrderContract($order, $tenantId, $signer)
    {
        $contractTemplate = $this->getOrderContractTemplate();
        if (empty($contractTemplate)) {
            throw new LogicException("missing order contract template config", ErrorCode::MISSING_ORDER_CONTRACT_TEMPLATE_CONFIG);
        }
        $contractService = ContractService::getInstance();


        /**
         * 根据业务模式生成不同的甲方合同
         */
        $businessMode = OptionsService::getInstance()->getBusinessMode();
        $fromTenantId = $order['from_tenant_id'];
        if ($businessMode === OptionsService::BUSINESS_MODE_TRIPARTITE) {
            $tenantService = TenantService::getInstance();
            $fromTenantId = $tenantService->getPlatformTenantId();
        }

        $contractData = [
            "name" => "{$order['name']} 订单合同" . date("YmdHi"),
            'contract_template_id' => $contractTemplate['id'],
            'from_tenant_id' => $fromTenantId,
            'to_tenant_id' => $tenantId,
            'start_time' => $order['start_time'],
            'end_time' => $order['end_time'],
            'param' => $order,
            'project_id' => $order['project_id'],
            'type' => 'contract_type_order',
            'order_id' => $order['id'],
            'money' => $order['money'],
        ];
        $stepCategory = model(StepCategoryModel::class)->where(['id' => $order['step_category_id']])->find();
        $extraParam = [
            'task_step_category_name' => $stepCategory['name'],
            'order_number' => $order['number']
        ];
        $contractData['extra_param'] = $extraParam;
        $contractData['dynamic_tables'] = [];
        $taskListTable = [
            'headers' => [
                '任务名称',
                '人日单价',
                '人日总数',
                '开始时间',
                '计划完成时间',
                '金额',
            ],
            "colWidthPercent" => [
                4,
                4,
                4,
                4,
                4,
                4
            ],
            "cellHeight" => 30,
            "cellHorizontalAlignment" => 0,
            "cellVerticalAlignment" => 5,
            "pageBegin" => -1,
            "theFirstHeader" => "任务清单",
            "datas" => [

            ]
        ];
        $orderTaskList = model(OrderTaskListModel::class)
            ->join("task ON task.id = order_task_list.task_id", "LEFT")
            ->where(['order_id' => $order['id']])
            ->field("task.name as task_name,task.plan_start_time,task.plan_end_time,order_task_list.*")
            ->select();

        $entityIdData = array_column($orderTaskList, 'entity_id', 'entity_id');


        $entityData = model(EntityModel::class)->where(['id' => ["IN", implode(',', $entityIdData)]])->select();
        $entityData = array_column($entityData, null, 'id');
        foreach ($orderTaskList as $orderTask) {
            $taskListTable['datas'][] = [
                $entityData[$orderTask['entity_id']]['name'] . $orderTask['task_name'],
                $order['man_day'],
                number_floor_precision($orderTask['cost_man_hour'], 2),
                get_format_date($orderTask['plan_start_time'], 0),
                get_format_date($orderTask['plan_end_time'], 0),
                $orderTask['money'],
            ];
        }

        $contractData['dynamic_tables'][] = $taskListTable;
        return $contractService->create($contractData, $tenantId, $signer);
    }

    /**
     * 获得合同模板信息
     * @return array|null
     */
    private function getOrderContractTemplate()
    {
        $contractTemplateId = OptionsService::getInstance()->getOptionsConfigItemData("order_contract_config", 'contract_template_id');
        return model(ContractTemplateModel::class)->find($contractTemplateId);
    }

    /**
     * 查询订单任务列表Item 通过RealTaskId
     * @param array $taskIdList
     * @param $status
     * @return array|false|mixed|string
     */
    public function getOrderTaskListByTaskIdList(array $taskIdList, $status = 'default')
    {
        if (empty($taskIdList)) {
            return [];
        }
        return $this->orderTaskListModel->where(['task_id' => ['IN', $taskIdList], 'status' => $status])->select();
    }

    /**
     * 查询订单任务列表Item 通过RealTaskId
     * @param int $realTaskId
     * @param array $where
     * @return array
     */
    public function getOrderTaskListItemByRealTaskId(int $realTaskId, $where = [])
    {
        return $this->orderTaskListModel->forceMasterDB()->where(['real_task_id' => $realTaskId,])->where($where)->find();
    }

    /**
     * 查询订单任务列表Item 通过TaskId
     * @param int $taskId
     * @param array $where
     * @return array|false|mixed|string|null
     */
    public function getOrderTaskListItemByTaskId(int $taskId, $where = ['order_task_list.status' => OrderTaskListModel::STATUS_DEFAULT])
    {
        return $this->orderModel
            ->join('order_task_list on `order`.id = order_task_list.order_id')
            ->where(['order_task_list.task_id' => $taskId])
            ->where($where)->field('order_task_list.*')->find();
    }

    /**
     * 获取订单信息 通过工序任务id
     * @param int $taskId
     * @param string $orderTaskListStatus
     * @return array|null
     */
    public function getOrderByStepTaskId(int $taskId, $orderTaskListStatus = OrderTaskListModel::STATUS_DEFAULT): ?array
    {
        return $this->orderModel->forceMasterDB()
            ->join("order_task_list ON order_task_list.order_id = order.id")
            ->where([
                '`order_task_list`.real_task_id' => $taskId,
                '`order_task_list`.status' => $orderTaskListStatus,
            ])
            ->field("`order`.*")
            ->find();
    }

    /**
     * 检查订单任务是否全部完成
     * @param array|null $order
     * @return bool
     */
    public function checkOrderTaskListDoneStatus(array $order)
    {
        $orderTaskIdData = $this->orderTaskListModel->where(['order_id' => $order['id']])->field("real_task_id")->select();
        $orderTaskIdData = array_column($orderTaskIdData, 'real_task_id');

        $taskQueryField = [
            'status.id',
            'status.code',
            'task.id',
            'task.code',
            'task.name'
        ];
        $taskQueryField = build_complex_query_fields($taskQueryField, '__');
        $taskData = model(TaskModel::class)
            ->join("status ON status.id = JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))", "LEFT")
            ->where(['task.id' => ['IN', implode(',', $orderTaskIdData)]])
            ->field($taskQueryField)
            ->select();

        $statusService = StatusService::getInstance();
        // 已完成
        $doneStatus = $statusService->getTaskDoneStatus();
        $rules = [$doneStatus['id']];
        $flag = true;
        foreach ($taskData as $task) {
            $task = separate_complex_query_data($task, '__');
            // 当任务状态不存在 或者任务状态不等于待发布状态  那么任务就是没有完成的
            if (!isset($task['status']) || !in_array($task['status']['id'], $rules)) {
                $flag = false;
            }
        }
        return $flag;
    }

    /**
     * 标记订单为待结算
     * @param array|null $order
     * @return bool
     * @throws \Exception
     */
    public function markOrderWaitForSettlement(array $order)
    {
        trace("更新订单状态为待发起结算", "DEBUG");
        $flag = model(OrderModel::class)->save([
            'id' => $order['id'],
            'status' => "wait_for_add_settlement",
        ]);
        if (!$flag) {
            trace("更新订单状态失败 {$order['id']}", "DEBUG");
            throw new LogicException("update order status failure", ErrorCode::ORDER_STATUS_UPDATE_FAILURE);
        }

        //集团订单没有结算,所以没有发起结算通知
        if ($order["type"] == "tenant_group") {
            return $flag;
        }

        //通知订单创建人发起结算
        try {
            $this->notifyOrderCreatorAddSettlement($order['id']);
        } catch (Throwable $e) {
            trace(format_exception_info($e), 'ERR');
        }
        return $flag;
    }

    /**
     * 待我审核订单统计
     * @return array
     * @throws \Exception
     */
    public function getMyReviewOrderCount()
    {
        $userId = \request()->getUserId();
        $orderModule = module_by_code('order');
        $res = model(OrderModel::class)
            ->join('review_request rr on rr.link_id = order.id and rr.module_id = ' . $orderModule['id'])
            ->join('review_request_node rrn on rrn.review_request_id = rr.id')
            ->where([
                'rrn.plan_reviewer' => $userId,
                'rrn.is_active' => 'yes',
                'order.status' => 'wait_for_party_a_review',
            ])
            ->field('count(distinct order.id) as count')
            ->select();
        return $res[0];
    }

    /**
     * 待审核订单列表
     * @param $param
     * @param $tenantId
     * @return array
     * @throws \Exception
     */
    public function getMyReviewOrderList($param, $tenantId)
    {
        // 作为甲方 审核节点激活的订单
        $orderFilter = [
            [
                "order.status" => "wait_for_party_a_review",
                "review_request_node.plan_reviewer" => \request()->getUserId(),
                "review_request_node.is_reviewed" => "no",
                "order.from_tenant_id" => $tenantId,
            ]
        ];
        $userId = \request()->getUserId();
        // 作为乙方 查出项目角色为商务制片的所有项目
//        $iCanConfirmProjectList = model(ProjectModel::class)
//            ->join('project_member on project.id = project_member.project_id')
//            ->where([
//                "project.belong_project_id" => ["neq", 0],
//                "project_member.role_code" => "business_producer",
//                "project_member.user_id" => $userId,
//                "project_member.is_delete" => 0,
//            ])
//            ->field("project.id, project.belong_project_id")
//            ->cache("order_service:get_my_review_order_list:user_project_member_cache:user-" . $userId, 60)
//            ->select();
//        if (!empty($iCanConfirmProjectList)) {
//            $orderFilter[] = [
//                "order.status" => "wait_for_party_b_ensure",
//                "order.project_id" => ["in", array_column($iCanConfirmProjectList, "belong_project_id")],
//                'order.to_tenant_id' => $tenantId,
//            ];
//            $orderFilter['_logic'] = "or";
//        }


        $orderFilter[] = [
            "order.status" => "wait_for_party_b_ensure",
            'order.to_tenant_id' => $tenantId,
        ];
        $orderFilter['_logic'] = "or";

        $param["param"]["filter"][] = $orderFilter;
        return $this->getOrderList($param['param'], $tenantId);
    }

    /**
     * 带发起计算订单列表
     * @param $param
     * @param $tenantId
     * @return array
     * @throws \Exception
     */
    public function getWaitForAddSettlementOrderList($param, $tenantId)
    {
        if (empty($param['param']['filter']['status'])) {
            $param['param']['filter'] = [
                'status' => 'wait_for_add_settlement',
                'from_tenant_id' => $tenantId,
            ];
        }
        return $this->getOrderList($param['param'], $tenantId);
    }

    /**
     * 创建订单通知订单审核人
     * @param array $orderDataList
     * @throws \Exception
     */
    private function notifyOrderReviewPeople(array $orderDataList)
    {
        $orders = array_column($orderDataList, 'order');
        $toTenantIdData = array_column($orders, 'to_tenant_id', 'to_tenant_id');
        $toTenantData = teamones_request('teamones-im', 'tenant/select', [
            'param' => [
                'filter' => [
                    'tenant.id' => ["-in", implode(',', $toTenantIdData)]
                ]
            ]
        ])['data'];
        $toTenantMap = array_column($toTenantData['rows'], null, 'id');
        $userIdData = array_column($orders, 'created_by', 'created_by');
        $reviewers = [];
        foreach ($orderDataList as $orderData) {
            $order = $orderData['order'];
            foreach ($orderData['review_data']['reviewers'] as $reviewer) {
                if ($reviewer['skip'] || $reviewer['user_id'] <= 0) {
                    continue;
                }
                $reviewers[$order['id']][$reviewer['user_id']] = $reviewer['user_id'];
                $userIdData[$reviewer['user_id']] = $reviewer['user_id'];
            }
        }
        $userData = model(UserModel::class)->where(['id' => ['IN', implode(',', $userIdData)]])->field("id,name,union_id")->select();
        $userMap = array_column($userData, null, 'id');
        $notifyMessages = [];
        foreach ($orders as $order) {
            $messageParam = [
                'first' => '有任务需要外包',
                'creator_name' => $userMap[$order['created_by']]['name'] ?? "",
                'order_name' => $order['name'],
                'supplier_name' => $toTenantMap[$order['to_tenant_id']]['name'] ?? "",
                'create_at' => date("Y/m/d H:i", $order['created']),
                'remark' => '请及时处理',
                'order_type' => $order['type'],
                'tenant_id' => $order['from_tenant_id'],
                'project_id' => $order['project_id'],
                'order_id' => $order['id'],
            ];

            //检查是否需要通知
            if (!isset($reviewers[$order['id']]) || count($reviewers[$order['id']]) == 0) {
                continue;
            }

            foreach ($reviewers[$order['id']] as $reviewer) {
                $notifyMessages[] = [
                    'param' => $messageParam,
                    'receiver_id' => $userMap[$reviewer]['union_id'],
                ];
            }
        }

        if (empty($notifyMessages)) {
            return;
        }
        $messageTemplateId = $this->getOrderReviewNotifyTemplateId();
        foreach ($notifyMessages as $notifyMessage) {
            Client::send('send_notify_message_v2', build_queue_data_with_xu([
                "param" => $notifyMessage['param'],
                'receiver' => $notifyMessage['receiver_id'],
                'template_id' => $messageTemplateId,
                'content_type' => 'card_message',
                'notice_type' => 'approval',
            ]));
        }
    }

    /**
     * 查询创建订单审核模板id
     * @return int
     */
    public function getOrderReviewNotifyTemplateId()
    {
        $messageTemplateId = OptionsService::getInstance()->getOptionsConfigItemData("message_notify_template_config", "order_review_notify_template_id");
        return (int)$messageTemplateId;
    }

    /**
     * 获得通知乙方确认订单模板id
     * @return int
     */
    public function getNotifyPartyBToAcceptOrderTemplateId()
    {
        $templateId = OptionsService::getInstance()->getOptionsConfigItemData("message_notify_template_config", "notify_party_b_to_accept_order_template_id");
        return (int)$templateId;
    }

    /**
     * 通知订单创建人发起结算
     * @param $id
     * @throws \Exception
     */
    private function notifyOrderCreatorAddSettlement($id)
    {
        $order = model(OrderModel::class)->find($id);
        $supplierTenant = teamones_request('teamones-im', 'tenant/find', [
            'param' => [
                'filter' => [
                    'id' => $order['to_tenant_id']
                ]
            ]
        ])['data'];
//        $contract = model(ContractModel::class)->where(['order_id' => $order['id']])->find();
        $messageParam = [
            'first' => '已通过审核',
            'supplier_name' => $supplierTenant['name'],
            'order_name' => $order['name'],
            'create_at' => date("Y/m/d H:i"),
            'remark' => '请及时发起结算流程',
            'order_id' => $order['id'],
//            'contract_id' => $contract['id']
        ];
        $messageTemplateId = $this->getNotifyOrderCreatorAddSettlementTemplateId();

        $notifyUser = model(UserModel::class)->find($order['created_by']);
        Client::send('send_notify_message_v2', build_queue_data_with_xu([
            "param" => $messageParam,
            'receiver' => $notifyUser['union_id'],
            'template_id' => $messageTemplateId,
            'content_type' => 'card_message',
            'notice_type' => 'message_order',
            'message_key' => 'settlement_add_notice',
        ]));
    }

    /**
     * 获得订单发起结算提醒模板id
     * @return int
     */
    private function getNotifyOrderCreatorAddSettlementTemplateId()
    {
        $messageTemplateId = OptionsService::getInstance()->getOptionsConfigItemData("message_notify_template_config", "notify_order_creator_add_settlement_template_id");
        return (int)$messageTemplateId;
    }

    /**
     * 订单审核结果通知模板id
     * @return int
     */
    public function getNotifyOrderReviewResultTemplateId()
    {
        $templateId = OptionsService::getInstance()->getOptionsConfigItemData("message_notify_template_config", "notify_order_review_result_template_id");
        return (int)$templateId;
    }

    /**
     * 乙方操作订单 结果通知
     * @param int $orderId
     * @param bool $isAccept
     * @throws \Exception
     */
    public function notifyPartyASupplierProcessOrderResult(int $orderId, bool $isAccept)
    {
        $order = model(OrderModel::class)->find($orderId);
        $creator = model(UserModel::class)->find($order['created_by']);
        $toTenantData = teamones_request('teamones-im', 'tenant/find', [
            'param' => [
                'filter' => [
                    'id' => $order['to_tenant_id'],
                ]
            ]
        ])['data'];
        $messageParam = [
            'first' => '供应商回复',
            'order_name' => $order['name'],
            'supplier_name' => $toTenantData['name'],
            'process_at' => date("Y/m/d H:i"),
            'process_result' => $isAccept ? "接受" : "拒绝",
            'remark' => $isAccept ? "请及时签署订单合同" : '请重新发包'
        ];
        $messageTemplateId = $this->getNotifyPartyASupplierProcessOrderResultTemplateId();
        $messageKey = 'party_b_accept_order_notify';

        Client::send('send_notify_message_v2', build_queue_data_with_xu([
            "param" => $messageParam,
            'receiver' => $creator['union_id'],
            'template_id' => $messageTemplateId,
            'content_type' => 'card_message',
            'notice_type' => 'message_order',
            'message_key' => $messageKey
        ]));
    }

    /**
     * 获得乙方接受/拒绝订单后通知模板id
     * @return int
     */
    private function getNotifyPartyASupplierProcessOrderResultTemplateId()
    {
        $templateId = OptionsService::getInstance()->getOptionsConfigItemData("message_notify_template_config", "notify_party_a_supplier_process_order_result_template_id");
        return (int)$templateId;
    }

    /**
     * 公共更新重写
     * @param $data
     * @param $currentCode
     * @return array
     * @throws \Exception
     */
    public function commonUpdate($data, $currentCode)
    {

        $commonService = CommonService::instance($currentCode);

        // 如果更新订单状态未乙方拒绝  那么通知甲方订单结果
        if (isset($data['status']) && $data['status'] == "party_b_deny") {
            try {
                $this->notifyPartyASupplierProcessOrderResult($data['id'], false);
            } catch (Throwable $e) {
                trace(format_exception_info($e), 'ERR');
            }
        }

        return $commonService->update($data);
    }

    /**
     * 创建订单群聊
     * @param int $orderId
     * @throws \Exception
     */
    public function createOrderChat(int $orderId)
    {
        $chat = teamones_request('teamones-im', 'oauth/find_chat', ['param' => ['filter' => ['link_id' => $orderId, 'link_type' => 'order']]])['data'];
        $order = model(OrderModel::class)->find($orderId);

        $orderParam = json_decode($order['param'], true);
        $chatUsers = [
            $orderParam['order_accept_people'] ?? 0,
            $order['party_a_person_in_charge'],
            $order['created_by'],
        ];
        $chatUsers = array_unique($chatUsers);
        if (!empty($chatUsers)) {
            $users = model(UserModel::class)->where(['id' => ['IN', implode(',', $chatUsers)]])->field("id,union_id")->select();
            $userMap = array_column($users, 'union_id', 'id');
            $chatUsers = array_map(function ($item) use ($userMap) {
                return $userMap[$item] ?? 0;
            }, $chatUsers);
            $chatUsers = array_filter($chatUsers, function ($item) {
                return (int)$item > 0;
            });
        } else {
            $chatUsers = [];
        }
        $orderHeadman = $orderParam['headman'] ?? 0;

        // 订单组长负责人是union_id不用查询
        if ($orderHeadman > 0) {
            $chatUsers[] = $orderHeadman;
        }
        $chatUsers = array_unique($chatUsers);


        if (empty($chat)) {
            teamones_request('teamones-im', 'oauth/create_chat', [
                'data' => [
                    'chat' => [
                        'name' => $order['name'],
                        'type' => 'group',
                        'link_id' => $orderId,
                        'link_type' => 'order',
                        'project_id' => $order['project_id'],
                        'from_tenant_id' => $order['from_tenant_id'],
                        'to_tenant_id' => $order['to_tenant_id'],
                    ],
                    'chat_users' => $chatUsers,
                    'owner' => 0
                ]
            ]);
            APP_DEBUG && trace("create chat {$order['name']} and users are " . var_export($chatUsers, true), "DEBUG");
            return;
        }
        if (!empty($chatUsers)) {
            teamones_request('teamones-im', 'oauth/invite_chat_user', [
                'data' => [
                    'chat_global_id' => $chat['global_id'],
                    'user_id' => $chatUsers
                ]
            ]);
            APP_DEBUG && trace("inviteChatUser to order chat {$chat['name']} " . var_export($chatUsers, true), "DEBUG");
        }
    }

    /**
     * 待甲方开票订单列表
     * @param $param
     * @param int $tenantId
     * @return array
     * @throws \Exception
     */
    public function getWaitForApplyInvoiceOrderList($param, int $tenantId)
    {
        $param['filter'] = $param['filter'] ?? [];

        $param['filter']['party_a_invoice_status'] = "no";
        $param['filter']['status'] = "done";
        $param['filter']['from_tenant_id'] = $tenantId;

        return $this->getOrderList($param, $tenantId);
    }

    /**
     * 查询外包项目任务在原始项目的任务
     * @param int $taskId
     * @param string[] $where
     * @return array|null
     */
    public function getSourceTaskByTaskId(int $taskId, $where = ['`order_task_list`.`status`' => 'default'])
    {
        $orderTaskItem = $this->orderModel
            ->join("order_task_list ON order_task_list.order_id = order.id", 'LEFT')
            ->where([
                '`order_task_list`.real_task_id' => $taskId
            ])
            ->where($where)
            ->field("`order_task_list`.task_id")
            ->find();
        if (empty($orderTaskItem)) {
            return null;
        }

        return model(TaskModel::class)->find($orderTaskItem['task_id']);
    }

    /**
     * 查询原始项目在外包项目的任务
     * @param $taskIdList
     * @return array
     */
    public function getSourceTaskListByTaskIdList($taskIdList, $onlyReturnIds = false): array
    {
        $orderTaskItemList = $this->orderTaskListModel->alias('otl')->join('`order` o ON o.id = otl.order_id')
            ->where([
                'otl.real_task_id' => ['IN', $taskIdList],
                'o.status' => ['IN', ['inprogress', 'wait_for_add_settlement', 'wait_for_review_settlement', 'wait_for_settlement', 'done']]
            ])
            ->field("otl.real_task_id,otl.task_id")
            ->select();
        if (empty($orderTaskItemList)) {
            return [];
        }
        $relationMap = array_column($orderTaskItemList, 'task_id', 'real_task_id');
        if ($onlyReturnIds) {
            return $relationMap;
        }

        $taskList = model(TaskModel::class)->where(['id' => ['IN', array_column($orderTaskItemList, 'task_id')]])->select();
        $taskList = array_column($taskList, null, 'id');
        foreach ($relationMap as &$taskId) {
            $taskId = $taskList[$taskId] ?? null;
        }
        return $relationMap;
    }

    /**
     * 查询外包项目任务在原始项目的任务
     * @param $taskId
     * @param string[] $where
     * @return array|null
     */
    public function getOutsideTaskByTaskId($taskId, $where = ['`order_task_list`.`status`' => 'default'])
    {
        $orderTaskItem = $this->orderModel
            ->join("order_task_list ON order_task_list.order_id = `order`.id", 'LEFT')
            ->where([
                '`order_task_list`.task_id' => $taskId,
                '`order_task_list`.real_task_id' => ['GT', 0],
            ])
            ->where($where)
            ->field("`order_task_list`.real_task_id")
            ->find();
        if (empty($orderTaskItem)) {
            return null;
        }

        return model(TaskModel::class)->find($orderTaskItem['real_task_id']);
    }

    /**
     * 查询外包项目任务在原始项目的任务
     * @param $taskIdList
     * @return array
     */
    public function getOutsideTaskListByTaskIdList($taskIdList): array
    {
        $orderTaskItemList = $this->orderTaskListModel->alias('otl')->join('`order` o ON o.id = otl.order_id')
            ->where([
                'otl.task_id' => ['IN', $taskIdList],
                'otl.status' => 'default',
            ])
            ->field("otl.real_task_id,otl.task_id")
            ->select();
        if (empty($orderTaskItemList)) {
            return [];
        }
        $relationMap = array_column($orderTaskItemList, 'real_task_id', 'task_id');

        $realTaskList = model(TaskModel::class)->where(['id' => ['IN', array_column($orderTaskItemList, 'real_task_id')]])->select();
        $realTaskList = array_column($realTaskList, null, 'id');
        foreach ($relationMap as &$realTaskId) {
            $realTaskId = $realTaskList[$realTaskId] ?? null;
        }
        return $relationMap;
    }


    /**
     * 生成订单外包文件传输列表(上游依赖文件) 甲方=>乙方
     * @param int $orderId
     * @param int $userId
     * @return array
     */
    public function generatedOrderTaskFileList(int $orderId, int $userId): array
    {
        $order = $this->orderModel->forceMasterDB()->find($orderId);
        $orderList = $this->orderTaskListModel->forceMasterDB()
            ->join('task ON task.id = order_task_list.real_task_id')
            ->where([
                'order_task_list.order_id' => $orderId,
                'order_task_list.status' => 'default',
            ])
            ->field('task.project_id,order_task_list.id,order_task_list.task_id')
            ->select();
        // 发给乙方的任务列表为空
        if (empty($orderList)) {
            return [];
        }
        $partyBProjectId = $orderList[0]['project_id'];
        $taskList = $this->orderTaskListModel
            ->forceMasterDB()
            ->alias('otl')
            ->join('task on task.id = otl.task_id')
            ->where(['otl.order_id' => $orderId, 'otl.status' => OrderTaskListModel::STATUS_DEFAULT,])
            ->field("otl.task_id,otl.real_task_id")
            ->select();
        $orderTaskFileList = [];
        $orderTaskUpstreamVersionListAdd = [];
        $orderTaskListTaskId = array_column($orderList, 'task_id');
        $orderTaskFileListAdded = model(OrderTaskFileListModel::class)->forceMasterDB()
            ->join('order_task_list on order_task_file_list.downstream_task_id = order_task_list.real_task_id and order_task_list.status = "' . OrderTaskListModel::STATUS_DEFAULT . '"')
            ->where([
                'order_task_file_list.order_id' => $orderId,
                'order_task_file_list.from_tenant_id' => $order['from_tenant_id'],
                'order_task_file_list.to_tenant_id' => $order['to_tenant_id']
            ])
            ->field('order_task_file_list.task_id as order_task_file_list_task_id')
            ->column('order_task_file_list_task_id');
        $upstreamTaskIdListAll = [];
        $taskListUpstreamList = TaskUpstreamService::getInstance()->getUpstreamTaskListBatch(array_column($taskList, 'task_id'));
        $upstreamTaskListAll = [];
        foreach ($taskList as $taskItem) {
            if (empty($taskListUpstreamList[$taskItem['task_id']])) {
                continue;
            }
            $task = $taskListUpstreamList[$taskItem['task_id']];
            // 上游任务列表
            $upstreamTaskList = array_column($task['upstream_task_list'], null, 'id');

            if (empty($upstreamTaskList)) {
                continue;
            }
            // 比较版本和人物信息  进行写入fileList
            foreach ($upstreamTaskList as $upstreamTaskItem) {
                $upstreamTaskIdListAll[$upstreamTaskItem['id']] = $upstreamTaskItem['id'];
                $upstreamTaskListAll[$upstreamTaskItem['id']] = $upstreamTaskItem;
                // 移除已经发送给乙方的任务
                // 上游任务在订单里
                if (in_array($upstreamTaskItem['id'], $orderTaskListTaskId)) {
                    APP_DEBUG && trace('上游任务在订单里', 'DEBUG');
                    continue;
                }
                // 检查是否已经添加过记录
                if (in_array($upstreamTaskItem['id'], $orderTaskFileListAdded) || isset($orderTaskFileList[$upstreamTaskItem['id']])) {
                    APP_DEBUG && trace('已经添加过记录', 'DEBUG');
                    continue;
                }

                $orderTaskFileList[$upstreamTaskItem['id']] = [
                    'order_id' => $orderId,
                    'from_tenant_id' => $order['from_tenant_id'],
                    'to_tenant_id' => $order['to_tenant_id'],
                    'task_id' => $upstreamTaskItem['id'],
                    'from_project_id' => $upstreamTaskItem['project_id'],
                    'entity_id' => $upstreamTaskItem['entity_id'],
                    'step_id' => $upstreamTaskItem['step_id'],
                    'step_category_id' => $upstreamTaskItem['step_category_id'],
                    'created' => time(),
                    'to_project_id' => $partyBProjectId,
                    'downstream_task_id' => $taskItem['real_task_id'],
                    'created_by' => $userId,
                    'version_id' => 0,
                ];
            }
        }
        $upstreamTaskIdListAll = array_values($upstreamTaskIdListAll);
        $res = [];
        if (!empty($orderTaskFileList)) {
            $orderTaskFileList = array_values($orderTaskFileList);
            try {
                $res['order_task_file_list'] = model(OrderTaskFileListModel::class)->addAll($orderTaskFileList);
            } catch (Throwable $e) {
                trace(format_exception_info($e), 'ERR');
                $res['order_task_file_list'] = format_exception_info($e);
            }
        }

        if (empty($upstreamTaskIdListAll)) {
            return $res;
        }

        $versionFileStorageInfoList = VersionService::getInstance()->getMaxTaskListVersionList($upstreamTaskIdListAll, ['version.is_publish' => 'yes']);
        $versionFileStorageInfoMap = array_column($versionFileStorageInfoList, null, 'task_id');
        if (empty($versionFileStorageInfoMap)) {
            return $res;
        }
        $orderTaskUpstreamVersionFilter = [
            'to_tenant_id' => $order['to_tenant_id'],
            'version_id' => ['IN', array_column($versionFileStorageInfoList, 'id')],
        ];
        $createdVersionIdList = model(OrderTaskUpstreamVersionModel::class)->forceMasterDB()->where($orderTaskUpstreamVersionFilter)->field('version_id')->column('version_id');

        foreach ($upstreamTaskListAll as $upstreamTaskItem) {
            $upstreamTaskId = $upstreamTaskItem['id'];
            if (!array_key_exists($upstreamTaskId, $versionFileStorageInfoMap)) {
                continue;
            }
            $versionId = $versionFileStorageInfoMap[$upstreamTaskId]['version_id'];
            //检查 当前任务 当前版本是不是已经添加过了
            if (in_array($versionId, $createdVersionIdList)) {
                continue;
            }
            //如果已下载已解压/已经添加过传输记录 那么就不需要建立传输记录
            $orderTaskUpstreamVersionListAdd[] = [
                'from_tenant_id' => $order['from_tenant_id'],
                'to_tenant_id' => $order['to_tenant_id'],
                'from_project_id' => $order['project_id'],
                'to_project_id' => $partyBProjectId,
                'entity_id' => $upstreamTaskItem['entity_id'],
                'task_id' => $upstreamTaskId,
                'version_id' => $versionId,
                'created_by' => $userId,
                'created' => time(),
                'updated' => time(),
            ];
        }
        if (empty($orderTaskUpstreamVersionListAdd)) {
            return $res;
        }
        try {
            $res['order_task_upstream_version'] = model(OrderTaskUpstreamVersionModel::class)->addAll($orderTaskUpstreamVersionListAdd);
        } catch (Throwable $e) {
            trace(format_exception_info($e), 'ERR');
            $res['order_task_upstream_version'] = format_exception_info($e);
        }
        return $res;
    }

    /**
     * 取消任务重合的订单
     * @param $id
     * @throws \Exception
     */
    public function cancelOtherSameOrder($id)
    {
        $orderTaskList = $this->orderTaskListModel
            ->join('`order` ON `order`.id = order_task_list.order_id')
            ->where(['`order`.id' => $id])
            ->field('order_task_list.task_id')
            ->select();

        if (!empty($orderTaskList)) {
            $taskIdList = array_column($orderTaskList, 'task_id');
            $otherOrderIdList = $this->orderTaskListModel
                ->join('`order` ON `order`.id = `order_task_list`.`order_id`')
                ->where([
                    '`order_task_list`.task_id' => ['in', implode(',', $taskIdList)],
                    '`order_task_list`.status' => OrderTaskListModel::STATUS_DEFAULT,
                    '`order_task_list`.order_id' => ['NEQ', $id],
                    '`order`.status' => ['NOT IN', ['invalid', 'cancel']],
                ])
                ->field('order_id')
                ->select();
            if (!empty($otherOrderIdList)) {
                $this->orderModel->modifyItem([
                    'id' => ['IN', implode(',', array_column($otherOrderIdList, 'order_id'))],
                    'status' => 'invalid',
                ]);
            }
        }

    }

    /**
     * 乙方操作订单
     * @param array $param
     * @param int $userId
     * @param int $tenantId
     * @return array|bool
     * @throws Exception
     * @throws Throwable
     */
    public function partyBHandleOrder(array $param, int $userId, int $tenantId)
    {
        $action = $param['is_accept'] ?? 'no';
        $partyBRespProducerId = $param['party_b_resp_producer_id'];
        $partyBRespProducerId = $partyBRespProducerId > 0 ? $partyBRespProducerId : $userId;
        if ($action === 'yes') {
            $res = $this->partyBAcceptOrder($param, $userId, $partyBRespProducerId, $tenantId);
        } else {
            $res = $this->partyBDenyOrder($param, $partyBRespProducerId, $tenantId);
        }
        return $res;
    }

    /**
     * 通过订单生成播放列表
     * @param $orderId
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function generatePlaylistPackage($orderId)
    {
        $order = model(OrderModel::class)->find($orderId);
        $mergeModuleConfig = StepService::getInstance()->getMergeModuleStepCategoryConfig();
        $orderMergeModuleCode = '';
        foreach ($mergeModuleConfig as $orderMergeModuleCode => $stepCategoryIds) {
            $stepCategoryIdList = explode(',', $stepCategoryIds);
            if (in_array($order['step_category_id'], $stepCategoryIdList)) {
                break;
            }
        }
        $contractService = ContractService::getInstance();
        $signerData = $contractService->getOrderSigner($orderId);
        $orderRealTaskList = model(OrderTaskListModel::class)->where(['order_id' => $orderId])->field('real_task_id')->select();
        $realTaskIdList = array_column($orderRealTaskList, 'real_task_id');
        $realEntityIdList = model(TaskModel::class)->where(['id' => ['IN', $realTaskIdList]])->field('entity_id')->select();
        $realEntityIdList = array_column($realEntityIdList, 'entity_id');
        return ReviewTaskService::getInstance()->assemblePlayList($order['to_tenant_id'], $signerData['b_signer'], $order['name'], $realEntityIdList, $orderMergeModuleCode, 'order', $order['id']);
    }

    /**
     * 获得订单文件状态
     * @param int $orderId
     * @return string
     */
    public function getOrderFileStatus(int $orderId)
    {
        /**
         *
         * 甲方制作中:  party_a_in_production
         * 等待甲方上传: wait_party_a_upload
         * 甲方已上传: party_a_uploaded
         * 乙方制作中: party_b_in_production
         * 等待乙方上传: wait_party_b_upload
         * 等待甲方下载: wait_party_a_download
         * 甲方已下载: party_a_downloaded
         *
         */
        $order = $this->orderModel->find($orderId);
        if (empty($order)) {
            throw new LogicException('order not found', ErrorCode::ORDER_NOT_FOUND);
        }
        $orderUpstreamTaskList = $this->orderTaskFileListModel->where(['order_id' => $orderId])->select();
        // 分离甲方传给乙方 和乙方传给甲方数据
        $from = [];
        $to = [];
        foreach ($orderUpstreamTaskList as $item) {
            if ($item['from_tenant_id'] === $order['from_tenant_id']) {
                $from[] = $item;
            } else {
                $to[] = $item;
            }
        }
        $statusService = StatusService::getInstance();
        $doneStatus = $statusService->getTaskDoneStatus();
        if (empty($from)) {
            // 订单没有上游需要传递
            if (empty($to)) {
                return 'party_b_in_production';
            } else {
                $to = array_column($to, 'task_id', 'task_id');
                // 判断是否全部完成
                $taskList = model(TaskModel::class)->where(['id' => ['IN', implode(',', $to)]])
                    ->field("JSON_UNQUOTE(JSON_EXTRACT(json,'$.task_status')) as task_status_id")
                    ->select();
                $taskList = array_filter($taskList, function ($task) use ($doneStatus) {
                    return $task['task_status_id'] == $doneStatus['id'];
                });
                if (count($taskList) >= count($to)) {
                    // 订单的任务都已经进入完成状态
                    return 'wait_party_b_upload';
                } else {
                    return 'party_b_in_production';
                }
            }
        } else {
            // 订单有上游任务需要传递
            // 检查上游任务是否都已经完成
            $fromTaskIdList = array_column($from, 'task_id', 'task_id');
            $taskList = model(TaskModel::class)->where(['id' => ['IN', implode(',', $fromTaskIdList)]])
                ->field("JSON_UNQUOTE(JSON_EXTRACT(json,'$.task_status')) as task_status_id")
                ->select();
            $taskList = array_filter($taskList, function ($item) use ($doneStatus) {
                return $item['task_status_id'] == $doneStatus['id'];
            });
            if (count($taskList) === count($fromTaskIdList)) {
                // 任务已经全部完成
                // 检查是否已经全部上传
                $fromGrouped = array_group_by($from, 'task_id');
                $taskMaxVersionIdList = [];
                $maxVersionDownloadedCount = 0;
                $hasZeroVersionId = false;
                foreach ($fromGrouped as $taskVersionList) {
                    $taskVersionListSorted = array_sort_by($taskVersionList, 'version_id', 'desc', false);
                    $maxTaskVersion = $taskVersionListSorted[0];
                    if ($maxTaskVersion['version_id'] === 0) {
                        $hasZeroVersionId = true;
                        break;
                    }
                    $taskMaxVersionIdList[] = $maxTaskVersion['version_id'];
                    if ($maxTaskVersion['is_download'] === 'yes') {
                        $maxVersionDownloadedCount += 1;
                    }
                }
                if ($hasZeroVersionId) {
                    return 'wait_party_a_upload';
                }
                $maxTaskVersionList = model(VersionModel::class)->where(['id' => ['IN', $taskMaxVersionIdList]])->field('id,is_uploaded')->select();
                $uploadedVersionCount = count(array_filter($maxTaskVersionList, function ($version) {
                    return $version['is_uploaded'] = 'yes';
                }));
                if ($uploadedVersionCount !== count($maxTaskVersionList)) {
                    // 没有全部上传完毕
                    return 'wait_party_a_upload';
                }
                if ($maxVersionDownloadedCount !== count($maxTaskVersionList)) {
                    // 没有全部下载完毕
                    return 'party_a_uploaded';
                }
                // 检查乙方任务是否全部完成
                $orderTaskList = model(OrderTaskListModel::class)->where(['order_id' => $orderId])->field('real_task_id')->select();
                $realTaskList = model(TaskModel::class)->where(['id' => ['IN', array_column($orderTaskList, 'real_task_id')]])
                    ->field("id,JSON_UNQUOTE(JSON_EXTRACT(json,'$.task_status')) as task_status_id")
                    ->select();
                $doneCount = count(array_filter($realTaskList, function ($task) use ($doneStatus) {
                    return $task['task_status_id'] == $doneStatus['id'];
                }));
                if (count($realTaskList) !== $doneCount) {
                    // 乙方任务还未完成
                    return 'party_b_in_production';
                }
                // 检查是否全部上传
                $toGrouped = array_group_by($to, 'task_id');
                $maxVersionDownloadedCount = 0;
                $taskMaxVersionIdList = [];
                foreach ($toGrouped as $taskVersionList) {
                    $taskVersionListSorted = array_sort_by($taskVersionList, 'version_id', 'desc', false);
                    $maxTaskVersion = $taskVersionListSorted[0];

                    $taskMaxVersionIdList[] = $maxTaskVersion['version_id'];
                    if ($maxTaskVersion['is_download'] === 'yes') {
                        $maxVersionDownloadedCount += 1;
                    }
                }
                $realTaskVersionList = model(VersionModel::class)->where(['id' => ['IN', $taskMaxVersionIdList]])->field('id,is_uploaded')->select();
                $uploadedVersionCount = count(array_filter($realTaskVersionList, function ($version) {
                    return $version['is_uploaded'] = 'yes';
                }));
                if ($uploadedVersionCount !== count($realTaskVersionList)) {
                    // 没有全部上传完毕
                    return 'wait_party_b_upload';
                }
                if ($maxVersionDownloadedCount !== count($realTaskVersionList)) {
                    // 没有全部下载完毕
                    return 'wait_party_a_download';
                }
                return 'party_a_downloaded';
            } else {
                // 任务没有全部完成
                return 'party_a_in_production';
            }
        }
    }

    /**
     * 更新订单文件状态
     * @param int $orderId
     * @return array|bool
     * @throws \Exception
     */
    public function updateOrderFileStatus(int $orderId)
    {
        $fileStatus = $this->getOrderFileStatus($orderId);
        $flag = model(OrderModel::class)->modifyItem(['id' => $orderId, 'file_status' => $fileStatus]);
        if ($flag === false && model(OrderModel::class)->getErrorCode() != \think\exception\ErrorCode::NO_DATA_HAS_BEEN_CHANGED) {
            throw new LogicException($this->orderModel->getError(), $this->orderModel->getErrorCode());
        }
        return $flag;
    }

    /**
     * 撤回订单
     * @param int $id
     * @return array
     * @throws Throwable
     */
    public function withdrawn(int $id)
    {
        /**
         * 撤回订单
         * 检查订单状态是否能撤回
         */
        $canRecallStatusList = ['wait_for_party_a_review', 'wait_for_party_b_ensure'];
        $order = $this->orderModel->find($id);
        if (empty($order)) {
            throw new LogicException('order not found', ErrorCode::ORDER_NOT_FOUND);
        }
        if (!in_array($order['status'], $canRecallStatusList)) {
            throw new LogicException('order current status can`t do this action', ErrorCode::ORDER_CANNOT_PERFORM_THIS_OPERATION);
        }
        $orderTaskList = model(OrderTaskListModel::class)->where(['order_id' => $id])->select();
        $orderTaskIdList = array_column($orderTaskList, 'id');
        $taskIdList = array_column($orderTaskList, 'task_id');
        model(OrderModel::class)->startTrans();
        try {
            $res['order'] = $this->orderModel->modifyItem(['id' => $id, 'status' => 'withdrawn']);
            $res['order_task_list'] = model(OrderTaskListModel::class)->where(['id' => ['IN', implode(',', $orderTaskIdList)]])->save(['status' => OrderTaskListModel::STATUS_INVALID]);
            $taskRevokeRes = TaskAssignService::getInstance()->revokeTaskAssigneeStatus(['id' => ['IN', implode(',', $taskIdList)]], request()->getTenantId());
            model(OrderModel::class)->commit();
            $res += $taskRevokeRes;
            return $res;
        } catch (Throwable $e) {
            model(OrderModel::class)->rollback();
            throw $e;
        }
    }

    /**
     * 外包订单查询项目列表
     * @param $param
     * @param $tenantKey
     * @return array
     * @throws \Exception
     */
    public function getProjectList($param, $tenantKey)
    {
        $filter = $param['filter'] ?? [];
        $order = $param['order'] ?? "project.created DESC";
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $orderProjectList['total'] = 0;
        $orderProjectList['rows'] = [];

        $projectIdList = model(OrderModel::class)
            ->field('project_id')
            ->where($filter)
            ->group('project_id')
            ->select();
        if (empty($projectIdList)) {
            return ['total' => 0, 'rows' => []];
        }
        $projectIds = array_column($projectIdList, 'project_id');
        unset($filter[$tenantKey]);
        $filter['project.id'] = ['IN', implode(',', $projectIds)];

        $orderProjectList['total'] = model(ProjectModel::class)->where($filter)->count();
        $presetFields = [
            "project.id",
            "project.tenant_id",
            "project.name",
            "project.code",
            "project.type",
            "project.belong_project_id",
            "project.public",
            "project.is_demo",
            "project.project_template_id",
            "project.rate",
            "project.description",
            "project.start_time",
            "project.end_time",
            "project.duration",
            "project.resolution",
            "project.delivery_time",
            "project.delivery_platform",
            "project.episodes",
            "project.created_by",
            "project.created",

        ];
        // 拼接参数fields并将参数字段起个别名
        $fields = array_unique(array_merge($presetFields, explode(',', $param['fields'] ?? null)));
        $fields = build_complex_query_fields($fields, '__');

        // 预设关联字段中的JSON数据
        $presetJoins['status'] = "status.id = JSON_UNQUOTE(JSON_EXTRACT(`project`.`json`, '$.project_status'))";
        $orderProjectData = model(ProjectModel::class)
            ->field(implode(',', $fields))
            ->join("LEFT JOIN `status` ON {$presetJoins['status']}")
            ->where($filter)
            ->order($order)
            ->page($page[0], $page[1])
            ->select();

        // 格式化数据
        foreach ($orderProjectData as $orderProjectItem) {
            $orderProjectList['rows'][] = separate_complex_query_data($orderProjectItem, '__');
        }
        return $orderProjectList;
    }

    /**
     * 获取等待签署的订单
     * @param $param
     * @param $tenantId
     * @return array
     * @throws \Exception
     */
    public function getWaitForSignOrderList($param, $tenantId)
    {
        $order = $param['order'] ?? "`order`.id DESC";
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $data['rows'] = [];

        $businessMode = OptionsService::getInstance()->getBusinessMode();
        $orderFilter = [];
        $orderQuery = [];
        if ($businessMode == OptionsService::BUSINESS_MODE_BOTH_SIDES) {
            $orderQuery = model(OrderModel::class)
                ->join("contract c on c.order_id = `order`.id");

            $orderFilter[] = [
                ["`order`.from_tenant_id" => $tenantId, "c.party_a_signed_time" => 0],
                ["`order`.to_tenant_id" => $tenantId, "c.party_b_signed_time" => 0],
                "_logic" => "OR"
            ];
        } elseif ($businessMode == OptionsService::BUSINESS_MODE_TRIPARTITE) {
            $orderQuery = model(OrderModel::class)
                ->join("contract ac on ac.order_id = `order`.id and ac.to_tenant_id = `order`.from_tenant_id")
                ->join("contract bc on bc.order_id = `order`.id and bc.to_tenant_id = `order`.to_tenant_id");
            $orderFilter[] = [
                ["`order`.from_tenant_id" => $tenantId, "ac.party_b_signed_time" => 0],
                ["`order`.to_tenant_id" => $tenantId, "bc.party_b_signed_time" => 0],
                "_logic" => "OR"
            ];
        }

        $orderFilter["`order`.status"] = 'wait_for_sign';
        $orderFilter[] = [
            "`order`.from_tenant_id" => $tenantId,
            "`order`.to_tenant_id" => $tenantId,
            "_logic" => "OR"
        ];
        $orderFilter["_logic"] = "AND";
        $data['rows'] = $orderQuery->where($orderFilter)->order($order)->field("`order`.*")
            ->page($page[0], $page[1])->select();

        $orderIds = [];
        $projectIds = [];
        $createdByIds = [];
        $personInChargeIds = [];
        $partyARespProducerIds = [];
        $partyBRespProducerIds = [];
        foreach ($data['rows'] as $dataRow) {
            $orderIds[] = $dataRow['id'];
            $projectIds[$dataRow['project_id']] = $dataRow['project_id'];
            $createdByIds[$dataRow['created_by']] = $dataRow['created_by'];
            $personInChargeIds[$dataRow['party_a_person_in_charge']] = $dataRow['party_a_person_in_charge'];
            $partyARespProducerIds[$dataRow['party_a_resp_producer_id']] = $dataRow['party_a_resp_producer_id'];
            $partyBRespProducerIds[$dataRow['party_b_resp_producer_id']] = $dataRow['party_b_resp_producer_id'];
        }

        // 合同信息
        $contractData = ContractService::getInstance()->getOrderContractList($orderIds, $tenantId);
        $contractData = array_column($contractData, null, 'order_id');

        // 项目信息
        $projectData = model(ProjectModel::class)->field("id,name,type")->where(['id' => ['IN', implode(',', $projectIds)]])->select();
        $projectData = array_column($projectData, null, 'id');

        // 集查询
        $taskList = model(OrderTaskListModel::class)->where(['order_id' => ['IN', implode(',', $orderIds)]])->select();
        $entityIds = array_column($taskList, 'entity_id', 'entity_id');
        $entityData = model(EntityModel::class)->where(['id' => ['IN', implode(',', $entityIds)]])->field('id,code,initial_episode_code')->select();
        $entityData = array_column($entityData, 'initial_episode_code', 'id');
        $orderEpisodeMap = [];
        foreach ($taskList as $task) {
            if (!empty($entityData[$task['entity_id']])) {
                $orderEpisodeMap[$task['order_id']][$entityData[$task['entity_id']]] = $entityData[$task['entity_id']];
            }
        }

        // 审批信息查询 (查询出没有审核的订单关联审核信息)
        $orderModule = Module::$moduleDictData['module_index_by_code']['order'];
        $reviewRequestModel = model(ReviewRequestModel::class);
        $reviewRequestData = $reviewRequestModel->join('review_request_node ON review_request.id = review_request_node.review_request_id', 'LEFT')
            ->field("review_request.link_id as order_id,review_request_node.id")
            ->where([
                'review_request.link_id' => ['IN', implode(',', $orderIds)],
                'review_request.module_id' => $orderModule['id'],
                'review_request_node.plan_reviewer' => request()->getUserId(),
                'review_request_node.is_reviewed' => "no",
            ])
            ->select();
        $reviewRequestData = array_column($reviewRequestData, null, 'order_id');

        // 创建者查询
        $createdByIds = array_unique(array_merge($createdByIds, $personInChargeIds, $partyARespProducerIds, $partyBRespProducerIds));
        $userData = model(UserModel::class)->field("json,uuid", true)->where(['id' => ['IN', implode(',', $createdByIds)]])->select();
        $userData = array_column($userData, null, 'id');

        //租户信息查询
        $tenantIdData = array_column($data['rows'], 'from_tenant_id', 'from_tenant_id');
        $tenantIdData = array_merge($tenantIdData, array_column($data['rows'], 'to_tenant_id', 'to_tenant_id'));
        $tenantData = teamones_request('teamones-im', 'tenant_authentication/select', ['param' => [
            'filter' => [
                "tenant_id" => [
                    "-in", implode(',', $tenantIdData)
                ]
            ],
            "fields" => "tenant_id as id,company_name,person_in_charge,person_in_charge_phone,person_in_charge_email"
        ]])['data'];
        $tenantData = array_column($tenantData['rows'], null, 'id');

        //结算信息
        $settlements = model(SettlementModel::class)->where(['is_reviewed' => "yes", 'order_id' => ['IN', implode(',', $orderIds)]])->select();
        $settlementsMap = array_column($settlements, null, 'order_id');

        $orderTaskWaitReview = [];

        $data['rows'] = array_map(function ($item) use (&$tenantData, &$userData, &$reviewRequestData, &$contractData, &$settlementsMap, &$orderTaskWaitReview, &$projectData, $orderEpisodeMap, $tenantId) {
            $item['from_tenant'] = $tenantData[$item['from_tenant_id']] ?? null;
            $item['to_tenant'] = $tenantData[$item['to_tenant_id']] ?? null;

            if ($tenantId == $item['from_tenant_id']) {
                $item['party_type'] = 'party_a';
            } elseif ($tenantId == $item['to_tenant_id']) {
                $item['party_type'] = 'party_b';
            }

            $item['creator'] = $userData[$item['created_by']] ?? null;
            $item['party_a_person_in_charge'] = $userData[$item['party_a_person_in_charge']] ?? null;
            $item['party_a_resp_producer'] = $userData[$item['party_a_resp_producer_id']] ?? null;
            $item['party_b_resp_producer'] = $userData[$item['party_b_resp_producer_id']] ?? null;
            $item['review_request_node'] = $reviewRequestData[$item['id']] ?? null;
            $item['contract'] = $contractData[$item['id']] ?? null;
            $item['settlement'] = $settlementsMap[$item['id']] ?? null;
            $item['review_manage_notify'] = isset($orderTaskWaitReview[$item['id']]);
            $item['project'] = $projectData[$item['project_id']] ?? '';
            $item['episode_list'] = [];
            if (!empty($orderEpisodeMap[$item['id']])) {
                $item['episode_list'] = array_keys($orderEpisodeMap[$item['id']]);
            }
            return $item;
        }, $data['rows']);
        return $data;
    }

    /**
     * 当前用户的外包审批
     * @param $param
     * @param $tenantId
     * @param $userId
     * @return array
     * @throws \Exception
     */
    public function getMySelfOutsideReviewOrderList($param, $tenantId, $userId)
    {
        $order = $param['order'] ?? "`order`.id DESC";
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];

        $orderModule = Module::$moduleDictData['module_index_by_code']['order'];
        $data['rows'] = model(OrderModel::class)
            ->join("review_request on order.id = review_request.link_id")
            ->join("review_request_node on review_request.id = review_request_node.review_request_id", "LEFT")
            ->where(['order.status' => 'wait_for_party_a_review',
                "review_request.module_id" => $orderModule['id'],
                "review_request_node.plan_reviewer" => $userId,
                'review_request_node.is_reviewed' => "no",
            ])
            ->order($order)
            ->field("`order`.*,review_request_node.id as review_request_node_id")
            ->page($page[0], $page[1])
            ->select();

        $orderIds = [];
        $projectIds = [];
        $createdByIds = [];
        $personInChargeIds = [];
        $partyARespProducerIds = [];
        $partyBRespProducerIds = [];
        foreach ($data['rows'] as $dataRow) {
            $orderIds[] = $dataRow['id'];
            $projectIds[$dataRow['project_id']] = $dataRow['project_id'];
            $createdByIds[$dataRow['created_by']] = $dataRow['created_by'];
            $personInChargeIds[$dataRow['party_a_person_in_charge']] = $dataRow['party_a_person_in_charge'];
            $partyARespProducerIds[$dataRow['party_a_resp_producer_id']] = $dataRow['party_a_resp_producer_id'];
            $partyBRespProducerIds[$dataRow['party_b_resp_producer_id']] = $dataRow['party_b_resp_producer_id'];
        }

        // 合同信息
        $contractData = ContractService::getInstance()->getOrderContractList($orderIds, $tenantId);
        $contractData = array_column($contractData, null, 'order_id');

        // 项目信息
        $projectData = model(ProjectModel::class)->field("id,name,type")->where(['id' => ['IN', implode(',', $projectIds)]])->select();
        $projectData = array_column($projectData, null, 'id');

        // 集查询
        $taskList = model(OrderTaskListModel::class)->where(['order_id' => ['IN', implode(',', $orderIds)]])->select();
        $entityIds = array_column($taskList, 'entity_id', 'entity_id');
        $entityData = model(EntityModel::class)->where(['id' => ['IN', implode(',', $entityIds)]])->field('id,code,initial_episode_code')->select();
        $entityData = array_column($entityData, 'initial_episode_code', 'id');
        $orderEpisodeMap = [];
        foreach ($taskList as $task) {
            if (!empty($entityData[$task['entity_id']])) {
                $orderEpisodeMap[$task['order_id']][$entityData[$task['entity_id']]] = $entityData[$task['entity_id']];
            }
        }

        // 创建者查询
        $createdByIds = array_unique(array_merge($createdByIds, $personInChargeIds, $partyARespProducerIds, $partyBRespProducerIds));
        $userData = model(UserModel::class)->field("json,uuid", true)->where(['id' => ['IN', implode(',', $createdByIds)]])->select();
        $userData = array_column($userData, null, 'id');

        //租户信息查询
        $tenantIdData = array_column($data['rows'], 'from_tenant_id', 'from_tenant_id');
        $tenantIdData = array_merge($tenantIdData, array_column($data['rows'], 'to_tenant_id', 'to_tenant_id'));
        $tenantData = teamones_request('teamones-im', 'tenant_authentication/select', ['param' => [
            'filter' => [
                "tenant_id" => [
                    "-in", implode(',', $tenantIdData)
                ]
            ],
            "fields" => "tenant_id as id,company_name,person_in_charge,person_in_charge_phone,person_in_charge_email"
        ]])['data'];
        $tenantData = array_column($tenantData['rows'], null, 'id');

        //结算信息
        $settlements = model(SettlementModel::class)->where(['is_reviewed' => "yes", 'order_id' => ['IN', implode(',', $orderIds)]])->select();
        $settlementsMap = array_column($settlements, null, 'order_id');

        $orderTaskWaitReview = [];

        $data['rows'] = array_map(function ($item) use (&$tenantData, &$userData, &$contractData, &$settlementsMap, &$orderTaskWaitReview, &$projectData, $orderEpisodeMap, $tenantId) {
            $item['from_tenant'] = $tenantData[$item['from_tenant_id']] ?? null;
            $item['to_tenant'] = $tenantData[$item['to_tenant_id']] ?? null;

            if ($tenantId == $item['from_tenant_id']) {
                $item['party_type'] = 'party_a';
            } elseif ($tenantId == $item['to_tenant_id']) {
                $item['party_type'] = 'party_b';
            }

            $item['creator'] = $userData[$item['created_by']] ?? null;
            $item['party_a_person_in_charge'] = $userData[$item['party_a_person_in_charge']] ?? null;
            $item['party_a_resp_producer'] = $userData[$item['party_a_resp_producer_id']] ?? null;
            $item['party_b_resp_producer'] = $userData[$item['party_b_resp_producer_id']] ?? null;
            $item['contract'] = $contractData[$item['id']] ?? null;
            $item['settlement'] = $settlementsMap[$item['id']] ?? null;
            $item['review_manage_notify'] = isset($orderTaskWaitReview[$item['id']]);
            $item['project'] = $projectData[$item['project_id']] ?? '';
            $item['episode_list'] = [];
            if (!empty($orderEpisodeMap[$item['id']])) {
                $item['episode_list'] = array_keys($orderEpisodeMap[$item['id']]);
            }
            return $item;
        }, $data['rows']);
        return $data;
    }

    /**
     * 设置集团化工序任务执行人
     * @param $orderId
     * @throws Throwable
     */
    public function setTenantGroupStepTaskExecutor($orderId)
    {
        $order = model(OrderModel::class)->forceMasterDB()->find($orderId);
        //非默认状态直接结束
        if (empty($order) || !in_array($order["status"], [OrderModel::STATUS_WAIT_FOR_PARTY_A_REVIEW, OrderModel::STATUS_PARTYB_ACCEPTED])) {
            return;
        }
        $orderTaskListModel = model(OrderTaskListModel::class)->forceMasterDB();
        $orderTaskList = $orderTaskListModel
            ->join('task on task.id = order_task_list.task_id')
            ->where(['order_id' => $order['id'], 'status' => OrderTaskListModel::STATUS_DEFAULT])
            ->field('order_task_list.*')
            ->select();

        if (empty($orderTaskList)) {
            return;
        }
        $orderTaskList = array_column($orderTaskList, null, 'task_id');
        $tenantId = $order['to_tenant_id'];
        $taskService = TaskService::getInstance();
        $orderTaskListModel->startTrans();
        try {
            $shadowProject = [];
            foreach ($orderTaskList as $taskItem) {
                // 外包分配任务
                $allocationTask = $taskService->setStepTaskExecutor($taskItem['task_id'], $order["party_a_resp_producer_id"], $order["party_b_resp_producer_id"], $tenantId, 'outside');
                $shadowTaskRes = $allocationTask['shadow_task'];
                $fromTask = $shadowTaskRes['from'];
                $toTask = $shadowTaskRes['to'];
                // 写入真实任务id 到任务清单中
                $orderTaskListModel->save([
                    'id' => $orderTaskList[$fromTask['id']]['id'],
                    'real_task_id' => $toTask['id']
                ]);
                if (empty($shadowProject)) {
                    $shadowProject = $allocationTask['shadow_project'] ?? [];
                }
            }
            //判定外部项目是否存在
            if (!empty($shadowProject)) {
                // 把乙方签署人加入项目成员中去
                try {
                    ContractService::getInstance()->addOrderSignerToProjectMember($order["party_b_resp_producer_id"], $shadowProject['id']);
                } catch (Throwable $e) {
                    trace(format_exception_info($e), 'ERR');
                }
                // 复制项目配置
                $projectService = ProjectService::getInstance();
                $projectService->copyProjectTemplateRelateConfig($shadowProject['id']);
            }
            // 生成任务依赖文件传输列表
            $orderService = OrderService::getInstance();
            Client::send('generate_order_task_file_list', build_queue_data_with_xu(['order_id' => $order['id'], 'user_id' => $order["party_b_resp_producer_id"]]), 3);
            // 取消其他相同任务订单
            $orderService->cancelOtherSameOrder($order['id']);
            // 更新订单文件状态
            Client::send('update_order_file_status', build_queue_data_with_xu(['id' => $order['id']]), 3);
            //任务生成完,更改为进行中的状态
            $orderModel = model(OrderModel::class);
            $flag = $orderModel->modifyItem([
                'id' => $order['id'],
                'status' => "inprogress"
            ]);
            if (!$flag && $orderModel->getErrorCode() != \think\exception\ErrorCode::NO_DATA_HAS_BEEN_CHANGED) {
                throw new LogicException("update order status failure", ErrorCode::ORDER_STATUS_UPDATE_FAILURE);
            }
            $orderTaskListModel->commit();
        } catch (Throwable $e) {
            $orderTaskListModel->rollback();
            throw $e;
        }
    }

    /**
     * 获取集团公司订单
     * @param $param
     * @return array|false|mixed|string
     */
    public function getTenantGroupOrder($param)
    {
        $query = $this->orderModel->where($param['filter']);
        if (array_key_exists("field", $param)) {
            $query->field($param['field']);
        }
        return $query->group("from_tenant_id,to_tenant_id")->select();
    }

    /**
     * 任务列表转换为甲方任务列表
     * @param array $taskList 任务列表
     * @return array|false|mixed|string
     */
    public function getSourceTaskListByTaskList(array $taskList)
    {
        return model(OrderTaskListModel::class)->alias('otl')
            ->join('task on task.id = otl.task_id')
            ->where(['otl.real_task_id' => ['IN', array_column($taskList, 'id')]])
            ->field('task.*')
            ->select();
    }
}
